ruby on rails delegate
TRANSCRIPT
“Ruby on Rails Delegate : Don’t break the Law of Demeter ! ”
Copyright 2016. Jyaasa Technologies. All Right Reserved
http://jyaasa.com
I am Sarbada Nanda JaiswalAssociate Software Engineer at Jyaasa Technologies
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.
In object-oriented programming
An object should not call methods through another object.
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
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
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
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
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 raisedNote 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.
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
ThanksCopyright 2016. Jyaasa Technologies. All Right Reserved
http://jyaasa.com