Delegation is a quite common practice in Ruby projects, if you consider proxies, mixins and composition as the ingredient of the Delegation Pattern. Know more about us: http://jyaasa.com
1. “Ruby on Rails Delegate :
Don’t break the Law of
Demeter ! ”
Copyright 2016. Jyaasa Technologies. All Right Reserved
http://jyaasa.com
2. I am Sarbada Nanda Jaiswal
Associate Software Engineer at
Jyaasa Technologies
3. Law of demeter
Each unit should have only limited knowledge about other
units: only units "closely" related to the current unit.
Each unit should only talk to its friends; don't talk to
strangers.
Only talk to your immediate friends.
5. When using Rails and the cool association feature, it
can be tempting to chain methods calls like this:
● product.provider.name
● provider.address.city
● company.building.city
6. These lines violate the Law of Demeter. To fix it, we
should change them to be :
● product.provider_name
● provider.address_city #or provider.city
● company.city
7. This way, it’s much cleaner and we don’t break the law anymore. But
to do that, we need to add a bunch of methods to our models :
class Product < ActiveRecord::Base
belongs_to :provider
def provider_name
provider.name
end
# More methods to access the provider's attributes
end
class Provider < ActiveRecord::Base
has_many :products
# Has a name attribute
end
8. We define methods for each attribute like this. But Rails has
a solution : Delegate
class Product < ActiveRecord::Base
belongs_to :provider
delegate :name, to: :provider, prefix: true
end
class Provider < ActiveRecord::Base
has_many :products
# Has a name attribute
end
9. Options:
o :to - Specifies the target object
o :prefix - Prefixes the new method with the target name or a custom
prefix
o :allow_nil - if set to true, prevents a NoMethodError to be raised
Note the use of the prefix key. It allows us to use product.provider_name instead of just
product.name since a product would probably have its own name.
10. Delegate is a really powerful feature that let you clean up your models.
Let’s see another example.
If we have a Company that belongs to a Building, we could do :
class Company < ActiveRecord::Base
belongs_to :building
delegate :street, :city, :country, to: :building, allow_nil: true
end
class Building < ActiveRecord::Base
has_many :companies
attr_accessible :street, :city, :country
end