Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
Rails' delegates are even more useful than I knew

File this under “things I wish I’d known about years ago”…

Do you use delegate in Rails? It’s a great way to avoid Law of Demeter violations. Let’s say you’re modeling people, who belong to households:

class Person
  belongs_to :household
  delegate :address, to: household
end

class Household
  # has a string attribute 'address'
end

Now we can get the address of a Person with the Demeter-friendly
person.address, rather than the trainwreck person.household.address.
When we decide suddenly that a person sometimes needs to override its
household’s address, we can change this to:

class Person
  belongs_to :household

  def address
    overriding_address || household.address
  end
end

and we don’t have to change any code which refers to person.address.

But! What about this?

class Person
  # has a string attribute 'name'
end

class Business
  belongs_to :owner, class_name: 'Person'
end

How do we get the name of a business’s owner? We could say
business.owner.name, but that’s a Demeter violation. We could delegate,
but then we’d have business.name, which would be wrong. Luckily, the
authors of delegate have thought of this:

class Business
  belongs_to :owner, class_name: 'Person'
  delegate :name, to: :owner, prefix: true
end

The prefix: true option gives us business.owner_name, which is much
better. You can also specify a custom prefix instead of true.

After doing this manually by defining methods for years, I feel silly to
learn that the prefix option has been around since 2008!

Comments
  1. Joe Van Dyk says:

    Using delegation like this always bugs me.

    Say you need to access a business owner’s email address, phone number, and address.

    Are you going to define delegators for each of those methods in the Business model?

  2. Peter Jaros says:

    It depends: why are you asking for those things?

    If you’re interested in properties of the business (say, you’re in businesses/show.html.haml), and one of those properties is the name of the business owner, you’d want to ask the business for it’s owner name. The business is responsible for figuring out where to look for that name.

    But, maybe you’re showing the owner as a Person box on the business’s page. Then your business/show template would `render business.owner`, which will render the partial `people/person`. That partial will have a local `person`, and since `person` is this partial’s friend, so it’s allowed to ask it for its name.

    If you’re looking for all three of those properties (email address, phone number, and address), you’re probably doing something more like the latter than the former. Here, the Law of Demeter is telling you not to add delegation but to use a partial.

  3. […] 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 […]

  4. Mitch Langlois says:

    Great explanation. Thank you :)

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *