Ruby on Rails 3.0.9を使用していて、いくつかの変数値を「動的に」設定しようとしています。つまり...
...私のモデルファイルには次のものがあります。
_attr_accessor :variable1, :variable2, :variable3
# The 'attributes' argument contains one or more symbols which name is equal to
# one or more of the 'attr_accessor' symbols.
def set_variables(*attributes)
# Here I should set to 'true' all ":variable<N>" attributes passed as symbol
# in the 'attributes' array, but variable names should be interpolated in a
# string.
#
# For example, I should set something like "prefix_#{':variable1'.to_s}_suffix".
end
_
これらの変数値をtrue
に設定するにはどうすればよいですか?
self.send(...)
メソッドを使用しようとしましたが、成功しませんでした(ただし、おそらく、そのsend
メソッドの使用方法がまったくわかりません...可能ですか? send
メソッドを使用して必要ですか?!)。
attr_accessor :variable1, :variable2, :variable3
def set_variables(*attributes)
attributes.each {|attribute| self.send("#{attribute}=", true)}
end
send
とinstance_variable_set
のベンチマーク比較は次のとおりです。
require 'benchmark'
class Test
VAR_NAME = '@foo'
ATTR_NAME = :foo
attr_accessor ATTR_NAME
def set_by_send i
send("#{ATTR_NAME}=", i)
end
def set_by_instance_variable_set i
instance_variable_set(VAR_NAME, i)
end
end
test = Test.new
Benchmark.bm do |x|
x.report('send ') do
1_000_000.times do |i|
test.set_by_send i
end
end
x.report('instance_variable_set') do
1_000_000.times do |i|
test.set_by_instance_variable_set i
end
end
end
そして、タイミングは次のとおりです。
user system total real
send 1.000000 0.020000 1.020000 ( 1.025247)
instance_variable_set 0.370000 0.000000 0.370000 ( 0.377150)
(1.9.2を使用して測定)
特定の状況(このように、アクセサがattr_accessor
を使用して定義されている場合)でのみ、send
とinstance_variable_set
が機能的に同等であることに注意してください。関係するアクセサーに何らかのロジックがある場合は違いがあり、2つのうちどちらのバリアントが必要かを決定する必要があります。 instance_variable_set
はivarを設定するだけですが、send
は実際にアクセサメソッドを実行します。
別の注意-2つのメソッドは別の側面で異なる動作をします。まだ存在しないivarをinstance_variable_set
すると、作成されます。 send
を使用して存在しないアクセサーを呼び出すと、例外が発生します。
あなたが求めている方法はinstance_variable_set
そうあなたの場合:
def set_variables(*attributes)
attributes.each {|attribute| self.instance_variable_set(attribute, true)}
end
def set_attributes(*attributes)
attributes.each do |attr|
self.send "#{attr}=", true
end
end
Rubyでは、setterメソッド名は=
で終わることに注意してください。
質問がRails 3であったことは知っていますが、Rails「変数値に動的にアクセスする方法」に関する4つの回答」を検索すると、質問が表示されました。テストしました。これは私のモデルであり、提案されたソリューションの代替としてうまく機能しました。
def set_variables(*attributes)
attributes.each {|attribute| self["#{attribute}"] = true}
end