Search code examples
ruby-on-railsdatabaselaw-of-demeter

When should I use delegate, and when should I use has_one :through?


Rails has two nice ways to avoid Law of Demeter violations in models.

The first is this:

class Restaurant < ActiveRecord::Base
    belongs_to :franchise
    delegate :owner, to: :franchise
end

The second is this:

class Restaurant < ActiveRecord::Base
    belongs_to :franchise
    has_one :owner, through: :franchise
end

What is the difference? Is there anything to recommend one option over the other in some or all instances?

The only difference I can detect is that the delegate option seems to generate two SQL queries to get at the latter record, whereas belongs_to :through seems to do it in one query.


Solution

  • has_one through: is rails relation and is optimized for some cases - for example it will use joins automatically to fetch record, also can be eager-loaded to avoid the N+1 problem when dealing with multiple Restaurants:

    Restaurant.all.includes(:owner).each{|r| some code accessing r.owner }
    

    If owner was a delegate code like the above (with .includes removed) would result in two queries per each Restaurant, but with eager loading they will be all fetched in one