How to set "dynamically" variable values?
attr_accessor :variable1, :variable2, :variable3def set_variables(*attributes) attributes.each {|attribute| self.send("#{attribute}=", true)}end
Here's the benchmark comparison of 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) endendtest = Test.newBenchmark.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 endend
And the timings are:
user system total realsend 1.000000 0.020000 1.020000 ( 1.025247)instance_variable_set 0.370000 0.000000 0.370000 ( 0.377150)
(measured using 1.9.2)
It should be noted that only in certain situations (like this one, with accessor defined using attr_accessor
) are send
and instance_variable_set
functionally equivalent. If there is some logic in the accessor involved, there would be a difference, and you would have to decide which variant you would need of the two. instance_variable_set
just sets the ivar, while send
actually executes the accessor method, whatever it does.
Another remark - the two methods behave differently in another aspect: if you instance_variable_set
an ivar which doesn't exist yet, it will be created. If you call an accessor which doesn't exist using send
, an exception would be raised.
The method you're after is instance_variable_set
so in your case:
def set_variables(*attributes) attributes.each {|attribute| self.instance_variable_set(attribute, true)}end