Bac*_*cko 20 ruby variables metaprogramming ruby-on-rails ruby-on-rails-3
我正在使用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
Run Code Online (Sandbox Code Playgroud)
如何将这些变量值设置为true
?
我尝试使用该self.send(...)
方法,但我没有成功(但是,可能,我不知道如何使用该send
方法...是否可以通过使用该send
方法来做到这一点?!).
Aru*_*nan 60
attr_accessor :variable1, :variable2, :variable3
def set_variables(*attributes)
attributes.each {|attribute| self.send("#{attribute}=", true)}
end
Run Code Online (Sandbox Code Playgroud)
这是send
vs 的基准比较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
Run Code Online (Sandbox Code Playgroud)
时间是:
user system total real
send 1.000000 0.020000 1.020000 ( 1.025247)
instance_variable_set 0.370000 0.000000 0.370000 ( 0.377150)
Run Code Online (Sandbox Code Playgroud)
(用1.9.2测量)
应当指出的是,只有在某些情况下(比如本,与存取器使用已定义的attr_accessor
)是send
和instance_variable_set
功能上等同的.如果涉及的访问器中存在某些逻辑,则会有所不同,您将不得不决定两者中需要哪种变体.instance_variable_set
只需设置ivar,send
实际执行访问器方法,无论它做什么.
另一个评论 - 这两种方法在另一个方面表现不同:如果你还有instance_variable_set
一个尚不存在的ivar,它将被创建.如果调用不存在的访问器send
,则会引发异常.