The new method in Ruby 1.9 is making some people happy and creative too.
The only problem with that in my opinion is that every one is fixed about using method chaining with the name “try” with a symbol as a parameter to escape from the:
@person.name unless @person.nil?
or
@person ? @person.name : nil
and for some strange reason they think it is natural to write:
@person.try(:name)
when I see the sentence above, the first thing I want to “try” is:
@person.try(:to_swim)
Ok, the last comment was not cool, but I thought it would be funny
So, what is this post about?
In Groovy there is a built’in language construct to solve this situation in a very cool way:
person?.nameThe method call after the “?” is only called if the previous expression was not nil.
I could not think in a way to implement any thing like that in ruby, but I think I came out with a satisfactory solution.
What do you think about flagging your method calls with “I know this can be null, but ignore it, it is a normal situation”?
No, I’m not telling you to write all this sentence in your code ![]()
the flag I’m using now is the “_” character.
I’m monkey patching ruby like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class NilClass alias :old_method_missing :method_missing def method_missing(methodname,*args) old_method_missing methodname, *args unless methodname.to_s =~ /.*_$/ end end class Object alias :old_method_missing :method_missing def method_missing(methodname,*args) methodname = (methodname.to_s.gsub(/(.*)_$/,'\1')).to_sym if respond_to? methodname send methodname,*args else old_method_missing methodname, *args end end end |
and you can use it like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #test classes class Named attr_accessor :name def initialize(name) @name = name end end class Person < Named attr_accessor :name, :company def initialize(name,company=nil) super(name) @company = company end end #Testing starts here def run_test puts @person.name_ puts @person.company_.name_ end @person = Person.new('Urubatan',Named.new('The Best')) run_test @person = nil run_test |
With this little method missing hack, we just put an “_” in the end of the method name we want to call and if the target object is nil the method will not be called and we will not get a NoMethodError.
Better yet, we can even pass arguments to the method we want to call
This way, we can use this solution only in situations we know it is safe.
What do you think about this?
I prefer the groovy solution, but I kine this one better than the “try” method
<updated>
Added one more link to the list in the beggining of the post (thanks coderr)
</updated>
If you enjoyed this post, make sure you subscribe to my RSS feed!
Tags: method_missing, monkeypatch, NoMethodError, ruby, try