在before_save过滤器上使用'send'

时间:2013-01-04 08:27:01

标签: ruby-on-rails ruby activerecord before-save

我在Rails模型上有一个名为:strip_whitespaces的before_save过滤器,就像这样

  before_save :strip_whitespaces

strip_whitespaces过滤器是一种私有方法,它按以下方式定义:

private 
  def strip_whitespaces
    self.name = name.split.join(" ") if attribute_present?("name")
    self.description = description.split.join(" ") if attribute_present?("description")
    self.aliases = aliases.split.join(" ") if attribute_present?("aliases")
  end

如何使用ruby的send方法使这个方法干掉?一旦我必须向此过滤器添加更多字段,这也会有所帮助。

我有这样的想法,但它不起作用

  %W[name description aliases].each do |attr|
    self.send(attr) = self.send(attr).split.join(" ") if attribute_present?(attr)
  end

2 个答案:

答案 0 :(得分:2)

我甚至会把它分成两个私有方法:

def strip_whitespaces
  %w(name description aliases).each do |attribute|
    strip_whitespace_from attribute
  end
end

def strip_whitespace_from(attr)
  send("#{attr}=", send(attr).split.join(" ")) if attribute_present?(attr)
end

请注意,您不需要执行self.send - 暗示self - 而且您也不需要执行send("#{attr}")因为插值无效,您可以做send(attr)

答案 1 :(得分:0)

这个答案很好地描述了ruby对象的send方法的setter语法 - How to set "programmatically"\"iteratively" each class object attribute to a value?

使用以下代码解决了这个特殊情况下的问题

def strip_whitespaces
  [:name, :description, :aliases].each do |attr|
    self.send( "#{attr}=", self.send("#{attr}").split.join(" ") ) if attribute_present?(attr)
  end
end

此处,代码首先获取属性self.send("#{attr}")的当前值,剥离空格,然后通过"#{attr}=" setter将其设置为属性。 attribute_present?(attr)ActiveRecord::Base类的一个方法,如果该属性不存在,则返回false。