Ruby — are you ‘calling a method’ or ‘sending a message’?
I’m a ruby developer and something that has confused me in the past has been the phrase ‘calling the method on X’ or ‘sending the message to X” where X is an object. It almost seemed like people were using the two phrases interchangeably when describing a method call on an object.
So which is right?
The answer, perhaps unsurprisingly, is both! Let’s look at why.
Let’s think about an object in Ruby for a moment. Say you have an instance of the String class and you assign it to the variable
example_object = "This is a string"
Okay, so our object has a bunch of methods available on it, in fact as an instance of the String class it has all of the instance methods that are included by default.
Sending the messages
I can send any message I like to our object with the
. notation. I can send the message
made_up_message_that_wont_work to it as such:
example_object.made_up_message_that_wont_work . Sending a message doesn’t mean that it will work, as it won’t in this case, but the point is that I can send any message I like, and when using dot notation it’s represented as the right hand side of the dot.
Calling the method
First of all, let’s check what methods we can call on our
example_object . We can do that by sending the message
methods to the object which will then call the correspondingly named method (the
=> [:include?, :%, :*, :+, :to_c, :unicode_normalize, :unicode_normalize!, :unicode_normalized?, :count, :partition, :unpack, :unpack1, :sum, :next, :casecmp, :casecmp?, :insert, :bytesize, :match, :match?, :+@, :-@, :upto, :index, :<=>, :replace, :succ!, :next!, :getbyte, :==, :===, :byteslice, :=~, :chr, :, :=, :clear, :scrub, :scrub!, :rindex, :downcase, :upcase, :empty?, :eql?, :setbyte, :upcase!, :capitalize, :swapcase, :dump, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :codepoints, :bytes, :chars, :concat, :lines, :reverse!, :<<, :freeze, :inspect, :ord, :start_with?, :prepend, :crypt, :reverse, :rjust, :intern, :scan, :ljust, :chop, :length, :size, :gsub, :succ, :chomp, :gsub!, :sub, :end_with?, :sub!, :lstrip!, :rstrip, :delete, :rstrip!, :chop!, :to_str, :to_sym, :center, :tr!, :tr, :tr_s, :to_s, :to_i, :lstrip, :tr_s!, :delete!, :squeeze!, :each_line, :chomp!, :strip!, :strip, :slice, :slice!, :rpartition, :each_byte, :to_f, :each_codepoint, :valid_encoding?, :ascii_only?, :encoding, :force_encoding, :each_char, :squeeze, :encode, :encode!, :hash, :b, :to_r, :<, :>, :<=, :>=, :between?, :clamp, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :public_send, :public_method, :singleton_method, :instance_variable_defined?, :define_singleton_method, :method, :instance_variable_set, :extend, :to_enum, :enum_for, :!~, :respond_to?, :object_id, :send, :display, :nil?, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variable_get, :instance_variables, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]
Side note, the
methods method is actually a method on the Object class, that our
example_object has because it is an instance of the String class, and the String class inherits from the Object class. You can see it in the above list as one of the methods available in our object.
This means our object can receive any of the messages listed above, and when it does receive them it will execute the correspondingly named method, if one exists.
You can send any message to any object using the dot notation (but doesn’t mean that it will work).
When you send a message to an object, and that object has the corresponding method as a public interface, then that message will call the method on the object.