Try(), try() again in Rails
everydayrails.com
everydayrails.com
To translate one of the example from the OP:
<%= @product.manufacturer.andand.name %>
<% if current_user.andand.is_admin? %>
<%= link_to 'Edit', edit_product_path(@product) %>
<% end %>
This syntax is simpler and more readable, even if there is more voodoo involved. Since when did we as rails devs care about that?(http://rubydoc.info/github/mongoid/mongoid/master/Mongoid/Ex...)
You're right, the name 'andand' isnt as clear as 'try,' it comes from its creation as a replacement for the use of the && operator as a guard.
If try() returned a proxy object that used method_missing to accept method calls rather than just being passed a symbol, we'd have the best of both worlds.
It is unfortunately a fairly wanton case of demeter violation, but rails is pretty much based on wanton demeter violation anyway, or at least it feels like that at times. Generally the times when I'm trying to write integration tests for some overly clever library.
I think by and large, most people don't use it not out of forgetfulness, but out of disdain for willy nilly calling methods on objects without knowing what might happen.
maybe(Person.find("geoff")) { |person| person.manager.authority_level.permissions }
without worrying about chaining things yourself. I've not used it in production code yet, as I haven't really had a chance to do due diligence on it - be interested to hear if anyone else has used it in anger...This makes it really easy to mix and match the two paradigms in your code: in places where it's okay for the object to just eat messages, you return null. In places where no value is a real error, you return nil. Either value can be converted to the other with a one-line statement, and to existing code, null looks like nil when queried (i.e., isNil returns true, ifNil: and ifNotNil: and friends behave as if null were nil, etc.).
Seems as if writing a similar tool for Ruby would be trivial.
With #try et al it's made obvious at the point the message is sent whether it'll be swallowed by nil (and that you're fine with this). To me this seems safer than having two classes of entities knocking round, one swallowing messages and one not, and no way to tell at a glance which is which.
(I've not used Smalltalk btw, so apologies if I've misunderstood...)
Sometimes, you want to do what you're saying, and have a brief snippet where you switch to message-eating null. That's easy enough using the built-in ifNil: message:
(foo ifNil: [ null ]) baz quux frob: bar.
If this is common, it'd be easy to add a method "try" to Object that returned self, and one to UndefinedObject that returned null, at which point you could do the same thing as Ruby: foo try baz quux frob: bar.
So either way, really.