在validation之前循环通过自我属性进行修改

我创建了一个简单的before_validation:

before_validation :strip_tabs def strip_tabs end 

在我的课程中,我想循环遍历所有属性并从每个值中删除制表符。 我在SO上找到的大多数post都是想要设置1个属性的人。 但我想编辑我的所有价值观。

问题:如何循环模型的所有自属性并进行编辑。

朋友建议了这个,但是content_column_names不存在:

 self.content_column_names.each {|n| self[n] = self[n].squish} 

更新1:更多代码:

 class PersonalInfo include ActiveModel::Validations include ActiveModel::Validations::Callbacks extend ActiveModel::Translation extend ActiveModel::Callbacks include Sappable require 'ext/string' attr_accessor \ :first_name, :middle_name, :last_name,:birthdate,:sex, :telephone,:street,:house_number,:city,:postal_code,:country, :e_mail, :nationality, :salutation, :com_lang validates :e_mail, :email => {:strict_mode => true} validate :validate_telephone_number validate :age_is_min_17? before_validation :strip_tabs def strip_tabs binding.remote_pry end def age_is_min_17? birthdate_visible = PersonalField.not_hidden.find_by_name "BIRTHDATE" if birthdate_visible && birthdate && birthdate > (Date.current - 17.years) @errors.add(:birthdate, I18n.t("apply.errors.birthdate")) end end def validate_telephone_number telephone_visible = PersonalField.not_hidden.find_by_name "TELEPHONE" telephone_current = telephone.dup if telephone_visible && telephone_current && !telephone_current.empty? if telephone_current[0] == '+' || telephone_current[0] == '0' telephone_current[0] = '' @errors.add(:telephone, I18n.t("apply.errors.telephone")) if !telephone_current.is_number? else @errors.add(:telephone, I18n.t("apply.errors.telephone")) end end end def initialize(hash) simple_attributes = [:first_name, :middle_name, :last_name,:birthdate,:sex, :telephone,:street,:house_number,:city,:postal_code,:country, :e_mail, :nationality, :salutation, :com_lang] simple_attributes.each do |attr| set_attr_from_json(attr, hash) end set_attr_from_json(:birthdate, hash) {|date| Date.parse(date) rescue nil} end end 

更新2:Rails版本:我正在使用Rails的3.2.17′

您可以执行以下操作:

 before_validation :strip_tabs def strip_tabs self.attributes.map do |column, value| self[column] = value.squish.presence end end 

但我认为.squish不适用于created_at, updated_at, id ,…因为它们不是String!

 def strip_tabs self.attributes.map do |column, value| self[column] = value.kind_of?(String) ? value.squish.presence : value end end 

由于您的类不是Rails模型 (ActiveRecord :: Base),您可以执行以下操作:

 def strip_tabs self.instance_variables.map do |attr| value = self.instance_variable_get(attr) value = value.squish if value.kind_of?(String) self.instance_variable_set(attr, value) end end 

这应该工作

 def strip_tabs self.attributes.each do |attr_name, attr_value| modified_value = ... # calculate your modified value here self.write_attribute attr_name, modified_value end end 

因为它不是ActiveRecord模型,所以你没有attributescolumn_names ,但是你的initialize函数中已经有了一个属性名称数组。 我建议将其变为常量,以便您可以在整个模型中访问它:

 class PersonalInfo include ActiveModel::Validations include ActiveModel::Validations::Callbacks extend ActiveModel::Translation extend ActiveModel::Callbacks include Sappable require 'ext/string' SIMPLE_ATTRIBUTES = [:first_name, :middle_name, :last_name,:birthdate,:sex, :telephone,:street,:house_number,:city,:postal_code,:country, :e_mail, :nationality, :salutation, :com_lang] attr_accessor *SIMPLE_ATTRIBUTES before_validation :strip_tabs def strip_tabs SIMPLE_ATTRIBUTES.each{ |attr| self[attr] = self[attr].squish } end ... def initialize(hash) SIMPLE_ATTRIBUTES.each do |attr| set_attr_from_json(attr, hash) end set_attr_from_json(:birthdate, hash) {|date| Date.parse(date) rescue nil} end end