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

时间:2014-05-22 14:31:41

标签: ruby-on-rails validation rails-activerecord

我创建了一个简单的before_validation:

  before_validation :strip_tabs

  def strip_tabs

  end

在我的课程中,我想循环遍历所有属性并从每个值中删除制表符。我在SO上找到的大多数帖子都是想要设置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'

3 个答案:

答案 0 :(得分:1)

您可以执行以下操作:

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起作用,...因为它们不是字符串!

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

答案 1 :(得分:0)

这应该有效

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

答案 2 :(得分:0)

因为它不是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