5

単純なオブジェクトがあるとしましょう。受け入れたいattr_accessor属性の s があり、オブジェクトのハッシュで初期化できるようにしたい:

class Example
  attr_accessor :foo, :bar

  def initialize( attributes = {} )
    attributes.each do |k,v|
      ...
    end
  end
end

send上記の attributes.each ブロックでは、次のように を使用する方がよいでしょうか。

send "#{k}=", v

またはinstance_variable_set次のように使用します。

instance_variable_set "@#{k}".to_sym, v

...またはまったく別のことをするために?

私が考えることができる違いは次のとおりです。

  • sendある時点でいずれかをattr_accessorsセッターメソッドに置き換えた場合、使用はより一貫性があります。

  • 予期しない値が渡された場合、使用sendすると発生しますNoMethodError

send私はこれらの理由で傾いています - 私は実際にNoMethodErrorは、偽の初期データのために提起される可能性が好きです。ただし、ここで見落としている他の要因、特にパフォーマンスとセキュリティの考慮事項はありますか?

洞察に感謝します。ありがとう!

4

3 に答える 3

5

私の答えは、送信を使用することです。

理由: アクセサーが存在しない場合でも、インスタンス変数は instance_variable_set で作成されます。おっしゃるとおり、send を使用すると NoMethodError が返されます。

于 2013-02-04T22:54:21.077 に答える
2

tryの代わりに使用できますsendsendメソッドが見つからない場合は NoMethod エラーを返し、メソッドが見つからない場合はniltryを返します。インスタンスメソッドには使用できません。try

例:

# k is a string or symbol, v a parameter value

try(k)
#=> nil

try(k, v)
#=> nil

ただし、インスタンス変数はメソッドで設定または読み取る必要がありますinstance_variable_setinstance_variable_get

# k is a string or symbol, v a value
instance_variable_set("@#{k}", v)
instance_variable_get("@#{k}")
于 2016-01-26T11:22:34.043 に答える
1

一般的な方法は send を使用することです。

まず、instance_variable_set余分なインスタンス変数をたくさん作成します。

次に、send はアクセサ メソッドを使用します。attr アクセサーの 1 つが再定義されている場合に非常に役立ちます。たとえば、次のようになります。

attr_accessor :foo

def bar=
  # something's happening here
end

避けるために、メソッドNoMethodErrorを使用する必要がありますrespond_to?

attributes.each do |k, v|
  send("#{k}=", v) if respond_to?(k)
end

手動で初期化する前、またはgemを使用する前に、余分な属性をトリミングすることもできます。gem 'strong_parameters'

于 2016-01-26T11:58:07.530 に答える