0

:strip_whitespacesこのようなRailsモデルで呼び出される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 メソッドを使用してこのメ​​ソッドを DRY-er にするにはどうすればよいですか? これは、このフィルターにさらにフィールドを追加する必要がある場合にも役立ちます。

このようなことを念頭に置いていましたが、うまくいきません

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

2 に答える 2

2

私はそれを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).

于 2013-01-04T10:39:55.677 に答える
0

sendこの回答には、ルビーオブジェクトのメソッドのセッター構文​​に関する適切な説明があります - 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 を介して属性に設定します。属性が存在しない場合に false を返すクラスattribute_present?(attr)のメソッドです。ActiveRecord::Base

于 2013-01-04T10:44:44.050 に答える