Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialRose Weixel
5,884 PointsWhat does the Ruby send method do?
I'm unclear as to what the send method is doing in the Formatter module of formatter.rb. Here's the code:
module Formatter
def display
self.class.format_attributes.each do |attribute|
puts "[#{attribute.to_s.upcase}] #{send(attribute)}"
end
end
end
I read some Ruby documentation on the send method, but it still doesn't make sense to me. What is it doing and why is it necessary here?
2 Answers
Geoff Parsons
11,679 PointsEvery time you call a method on an object you're "sending" that object a "message" where the message is the name of the method you called. If you call #to_s on a FixNum you're sending the message to_s
to the instance of the class FixNum.
The send
method allows you to send a message (call a method) when you won't know the name of that method until runtime. In this particular example you're getting a list of attributes, printing each attribute name as well as its value. The only way to get the value is to actually call the method.
Hope that helps!
Antoine Boillot
10,466 PointsHi all,
For those having a hard time understanding Geoff's answer (no offense Geoff), I did a few web searches and managed to understand the following :
As Jason already explained when writing the following :
attr_accessor :name
what the program is really doing is the following :
def name
@name
end
def name=(str)
@name = str
end
The send methods allows to call a method using the following syntax :
send(:method_to_call)
Meaning, using an example, that :
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = "Test"
puts person.name
is equivalent to typing the following :
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.send(:name=, "Test")
puts person.send(:name)
Now if we go back to the code Jason is typing in this example. The following...
def display
self.class.format_attributes.each do |attribute|
puts "[#{attribute.to_s.upcase}] #{send(attribute)}"
end
end
...calls
format_attributes
which is a class method hence you do:
self.class.format_attributes
and since this method is suppose to return an array of attributes, which are passed as symbols:
formats :name, :phone_number, :email, :experience
Hence
@format_attributes = [:name, :phone_number, :email, :experience]
Now in each block with attribute, you have:
puts "[#{attribute.to_s.upcase}] #{send(attribute)}"
Which can be translated to, for an instance:
puts "[#{:name.to_s.upcase}] #{send(:name)}"
And by using the send method on :name, the program will call the following methods
def name
@name
end
That's why you manage to get the value of the attribute, the instance variable @name being already defined through
resume.name = "Jason"
Hope this helps.
Cheers,
Allen Wang
3,439 PointsWow that's a great explanation! Thx for really clearing things up. I would be completely lost without this!
Víctor Rico
17,808 PointsThanks Antoine Boillot. Very well explained.
I wonder why Jason didn't explained those concepts.
Rose Weixel
5,884 PointsRose Weixel
5,884 PointsThanks, that made it a lot clearer for me.