delegate is neat trick that allows one to write cleaner, neater code. Particularly when dealing with ActiveRecord associations, delegate makes it possible to “outsource” a method to an associated object.
Without delegate, when dealing with a Chapter object, you’d need to access the book’s author via chapter.book.author. With delegation, this can be neatly shortened to chapter.author, with the .author getting handed off to the associated Book object.
An object can delegate multiple methods to its association, as shown in the example below. Another handy option is to use prefixes with delegate. For instance, using the same approach as above to refer to the book’s title would create chapter.title, which is confusing. With prefixes, however:
(Of course, if chapters had their own titles, the above code would make them inaccessible, but that’s what you get with contrived examples. See this post on the Pivotal Labs’ blog for a solution.)
One final tidbit to touch upon is that delegate is not limited to deliberately created methods and attributes but extends equally well to those created behind the scenes by the association:
For more on delegate, including custom prefixes and how to handle NoMethodErrors, see the API Docs.
“Use curly braces for single-line blocks and do..end for multi-lines blocks.” After seeing various permutations of that statement dozens of times, one can come to believe that the difference between the two is purely stylistic and that there is no practical reason to opt for one vs. the other. Most of the time, that is, indeed, true. Until that one-time-in-a-thousand when it’s not.
The trouble with do..end vs. {} can show up thanks to (a) Ruby’s laid-back attitude towards syntax, and (b) the fact that the two kinds of block delimiters do not behave 100% identically.
The syntax slackness in question is the optional usage of parentheses around method parameters. For instance, the following line pairs of code are identical:
The parentheses can be safely omitted from method calls in the vast majority of cases. That is, unless a block is involved, which brings us to (b).
The not-so-subtle difference between do..end and {} is their order of precedence - the curly braces rank higher on that score than do..end. This means that in a parentheses-less method call, the curly braces will bind the block to the preceding parameter, while do..end will bind it to the method.
Example:
The first command was equivalent to
while the second was interpreted as
In the first case, the block was passed to .map, which evaluated it and then gave the result back to puts. In the second case, the block was passed to puts, which ignored it and only reported that calling .map on an array yields an Enumerator object.