Ruby 101: Methods and messages
I hope that someone gets my
I hope that someone gets my
I hope that someone gets my
Message in a bottle
– The Police
Got a great question from Scott Porad the other day, asking about this line of code that’s produced by the scaffold generator in Rails 1.2 (note, in Scott’s application, his model is called content):
My question has to do with this line:
<td ><%= h content.send(column.name) %></ td>
What exactly is content.send(column.name) doing?
We all know that Ruby is an object-oriented language. However, many of us who are accustomed to .NET or Java may not realize that Ruby is really based on message passing, not method calling. The difference is so subtle that you can start using Ruby right away, and get pretty far, without ever knowing the difference. But this line in the scaffold code takes advantage of message passing to great effect.
When you write a Ruby class and define some methods inside of it, those methods are just predefined responses to certain messages.
class Thermometer
def temperature
75
end
end
To think in terms of message passing instead of methods, try to read this code out loud as, “This is class Thermometer. It can respond to a message named ‘temperature’. It will respond with 75 when it receives the message.”
It looks like a method call in your previous favorite language, and the message-calling syntax in Ruby looks like the method-calling syntax in that old language, too:
t = Thermometer.new
puts "It is " + t.temperature " + degrees outside."
When the Ruby interpreter sees t.temperature, it passes the message temperature to the t object. There are actually two ways we could have sent this message to the object. The first is what we did here. But there’s another, more generic way to send a message to an object, and that’s with the send method that’s available to every Ruby object:
t = Thermometer.new
puts "It is " + t.send('temperature') " degrees outside."
Here we sent the message named ‘temperature’ to the object. Since Thermometer has defined a response to the temperature message, Ruby is able to locate that response and execute it.
This means that you can write code that does not know method names a priori. Let’s go back to the scaffold code. When you run script/generate scaffold Product, the generator has no idea what columns your Product table will have. Yet it is able to generate that code that will automatically display all of the data in your table. It’s able to do this by first reflecting on your table for the column names, and then asking your model for the value of the attribute with that same name:
product.send(column.name)
So in this code, the product object is being passed a message, and it’s using the column name as the name of the message. ActiveRecord responds by returning the value of that column in the database. Beautiful!
In fact, your code can first find out if a given object will respond to a given message with respond_to?:
t = Thermometer.new
if t.respond_to? 'temperature'
puts "Yes, it can tell you the temperature"
else
puts "No, it can not tell you the temperature"
end
Today we looked at one way an object can respond to this message: providing a predefined response to a specific, named message. There’s another way to respond to messages, without writing def blocks at all.
But as Alton Brown likes to say, that’s another show.
Questions? Clear as mud? Drop me a comment.Ready to learn more? Sign up now for Essential Rails



Wow! really? I didn't know at all. Thanks for a great article.
Ruby continues to blow my mind. Great post.
Sweet post :-)
You might wanna put a lil mention somwhere that send() will allow you to call private methods too. Which is something very likely to be changed in ruby 2.0 for cases where you call send() with a receiver.
I love the send method, you can really current down on the code and it also helps keeping away from dirty eval statements.
Be careful when using respond_to? in hot sections of production code--it's slooow. Especially for ActiveRecord models.
Isn't the distinction between message sending and method calling a semantic one? Language A could use message sending and Language B could use method calling but internally they might both implement method dispatch in the same manner.
Undoubtedly the send method is a powerful and useful tool but I see no logical reason why Java (for example) couldn't have an "invoke" method on Object that does the same thing. It's just not architected to be that useful.
@John: You can do the equivalent in Java using the Reflection API. You can get pretty close to the brevity in Ruby if you use a wrapper like Apache Commons BeanUtils - http://commons.apache.org/beanutils/apidocs/
@Jeremy: Yes, I'm aware of that, thanks. I wasn't looking to actually do it in Java, I was trying to make the point that the difference between whether you think of objects as sending messages to one another or invoking methods on each other is semantic rather than technical. Or perhaps I'm completely wrong and it runs deeper than that...?
@John and @Jeremy: Actually, the difference is important, and it's one of the differences between a static language like Java/C# versus a dynamic language like Ruby. Even with reflection, the list of methods is fixed at compile time.
In Ruby objects can respond to messages without having predefined methods for them. In other words, without having a method dispatch table entry for your message. This is what method_missing is all about, and perhaps I'll follow up soon with an article about how that works.
Thanks Jeff - makes sense. Stupidly, I'd forgotten that Ruby lets you send messages to objects where the message doesn't exist until runtime. A good example being ActiveRecord's dynamic finders.
Exactly! And my hunch is that's also where the performance problems are that Larry was referring to.
@Jeff : Well, that hunch is certainly not correct.
Also worth mentioning is that send also exists as send, and only send (along with id_) will print warnings when you're trying to undefine them (and $VERBOSE is on). So it's likely safer to use _send than it is to use just plain send if you're dealing with objects that may be modified beyond what you've done.
Er... That was
send...facepalm... Fine. That was underscore-underscore-send-underscore-underscore...
It's a shame the whole world's still using java..
Thanks, this is great from a C# developer's perspective.
http://firsthotsex.net/best/nymphet-ukrainian-underage.html nymphet ukrainian underage
http://movie-hentai.net/bigboard/ayami-kojima-manga.html ayami kojima manga ayanami hentai pic rei http://movie-hentai.net/bigboard/ayanami-hentai-pic-rei.html ayanami hentai pic rei ayanami hentai rei http://movie-hentai.net/bigboard/ayanami-hentai-rei.html ayanami hentai rei ayanami hentai rey http://movie-hentai.net/bigboard/ayanami-hentai-rey.html ayanami hentai rey ayanami manga http://movie-hentai.net/bigboard/ayanami-manga.html ayanami manga ayanami manga rei
Sir !!! Hats off to you and your way of explaining things in such a lucid language. I am a student of ruby and rails ...and your articles make us Rich ! really !!
Thanks again,
Warm regards
Sunil
sleepingly underclassman hederaceous castanet deacidification immure soapmaker crouchingly Bathurst Macquarie Rover Crew http://phact.org/e/z/freewire.htm