Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set "dynamically" variable values?

Tags:

I am using Ruby on Rails 3.0.9 and I am trying to set "dynamically" some variable values. That is...

... in my model file I have:

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 

How can I set those variable values to true?


I tried to use the self.send(...) method, but I did not succeed (but, probably, I don't know how to use at all that send method... is it possible do to that I need by using the send method?!).

like image 390
Backo Avatar asked Aug 16 '11 13:08

Backo


2 Answers

attr_accessor :variable1, :variable2, :variable3  def set_variables(*attributes)   attributes.each {|attribute| self.send("#{attribute}=", true)} end 
like image 114
Arun Kumar Arjunan Avatar answered Oct 09 '22 09:10

Arun Kumar Arjunan


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)   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 

And the timings are:

      user     system      total        real send                   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.

like image 20
Mladen Jablanović Avatar answered Oct 09 '22 09:10

Mladen Jablanović