18

I'm trying to understand the following Ruby code.

It looks like attrs is a hash that gets passed as an argument with a default value of an empty hash.

Then attrs.each iterates over the key, value pairs in the hash (|k,v|).

What effect is achieved by calling self.send on the elements of the key value pair during this iteration?

def initialize(attrs = {}, *args)
  super(*args)
  attrs.each do |k,v|
    self.send "#{k}=", v
  end
end
franz
  • 397
  • 1
  • 3
  • 8
  • +1 I love using this code for flexible object creation/initialisation. See my answer @ http://stackoverflow.com/questions/1778638/idiomatic-object-creation-in-ruby/5272354#5272354 – abe Mar 11 '11 at 11:34

1 Answers1

27

send calls the method in the first parameter, and passes the rest of the parameters as arguments.

In this case I assume what's in attrs is a list of attributes. Let's say it's something like this:

{ :name => "John Smith" }

So then in the loop, it does this:

self.send "name=", "John Smith"

which is equivalent to

self.name = "John Smith"
Sarah Mei
  • 18,154
  • 5
  • 45
  • 45
  • Cool. Thanks. So, that means in your example name becomes a class method, right - because of [self.]name? – franz Jun 10 '09 at 02:46
  • 3
    First of all, that example isn't creating a method at all -- it's calling the method `name=`, which must already exist. Secondly, self inside an instance method (such as initialize) refers to the instance. So this is calling an instance method. – Chuck Jun 10 '09 at 03:06
  • Its worth mentioning that the `name=` methods are automatically created by the `attr_accessor :name` helper. – Joseph Pecoraro Jun 10 '09 at 03:50
  • The methods being called by #send are _NOT_ class methods; they are instance methods. "self." is used to define or call class methods from class scope, or to define or call instance methods from instance scope. #initialize is an instance method, so its scope is instance scope. – James A. Rosen Jun 10 '09 at 14:46