Why would I do that?What does this mean for how we actually write our code though?In a basic Rails application, if you’re chaining together methods on your view pages (or wherever your users are interfacing with your application), you want to avoid chaining too many methods.
This is for a couple of reasons:Responsibility: views should be in charge of returning info to users, not incorporating the logic to get said info.
Protection: ensures that changes to various model logic is encapsulated in the model itself, where it has a smaller chance of impacting the end-user experience.
The rule of thumb is that if you find you are chaining together more than one method in your view, then you’re violating the Law of Demeter and should look to try and pare that down to one method (Hence, the “one-dot” rule I mentioned earlier).
For instance, if we wanted to display the number of houses a sellsword is currently serving, we could chain together a couple of methods in our view like this:As you can see, we’ve got three methods chained to our instance variable , thus violating the Law of Demeter — it should not be our view’s responsibility to implement the logic to pull this information, but rather the model itself to perform the logic and our view to just displays the results of said logic.
How can we improve this?Let’s refactor this code by adding a #contracts_count instance method to our Sellsword model:We can then change our view method to be more in line with the Law:Another example — What if our knight page has a section to display the knight’s house info?.We could do something like the following:Once again however, we are violating the Law of Demeter.
In this case, it doesn’t really make sense to make an instance method for each of these.
Doing so would clutter our code and methods should generally be reserved for more complex logic, like our count from above.
Enter the #delegate method!.The delegate method is one of those “magical” Rails methods that allows us to be dedicated adherents to the Law of Demeter.
Using the delegate method, we can add the following code to our Knight model:which changes our view code to instead be:(Note that I used @knight.
house_name instead of @knight.
name because both knight’s and houses have names)Great!.Now our code has been reformatted to follow the Law of Demeter, thus making it less prone to future mistakes and, dare I say, a bit cleaner to read as well.
Following the Law can be hard, but as shown above, utilizing helper methods and the Rails #delegate module are just a few ways we can improve our code so we don’t end up in developer’s court…I’ll see myself out.
Demeter: It's not just a good idea.
It's the law.
In response to my recent post about #try being a code smell, a lot of people made the reasonable objection that thewww.
comdelegate (Module) – APIdockEdit descriptionapidock.
comRails Best Practices – the Law of DemeterEdit descriptionrails-bestpractices.