Download - Ruby on rails delegate
![Page 1: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/1.jpg)
“Ruby on Rails Delegate : Don’t break the Law of Demeter ! ”
Copyright 2016. Jyaasa Technologies. All Right Reserved
http://jyaasa.com
![Page 2: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/2.jpg)
I am Sarbada Nanda JaiswalAssociate Software Engineer at Jyaasa Technologies
![Page 3: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/3.jpg)
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.
![Page 4: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/4.jpg)
In object-oriented programming
An object should not call methods through another object.
![Page 5: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/5.jpg)
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
![Page 6: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/6.jpg)
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
![Page 7: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/7.jpg)
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
![Page 8: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/8.jpg)
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
![Page 9: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/9.jpg)
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.
![Page 10: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/10.jpg)
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
![Page 11: Ruby on rails delegate](https://reader036.vdocuments.mx/reader036/viewer/2022091121/58a708fa1a28ab4c438b6133/html5/thumbnails/11.jpg)
ThanksCopyright 2016. Jyaasa Technologies. All Right Reserved
http://jyaasa.com