One step further in modularization terms is to put those extension methods into a separate module, because it is a matter of:
- reuseability (logic can be reused)
- concern (logic is consolidated in a concerning module)
Imagine the example:
class Recipe < ActiveRecord::Base def to_s "#{name} (#{time})" end end class Cook < ActiveRecord::Base has_many :recipes do def to_s map(&:to_s).join(', ') end def [] term where("#{proxy_association.klass.table_name}.name LIKE ?", "%#{term}%") end end endand a use case like:
Cook.first.recipes['cookie'].to_s => "Chocolate Chunk Cookies (30), Amish Cookies (60)"can be refactored by moving both Proxy extension methods into a module:
module HasManyProxyExtension module NameSearchableAndHumanizable def [] term where("#{proxy_association.klass.table_name}.name LIKE ?", "%#{term}%") end def to_s map(&:to_s).join(', ') end end end class Cook < ActiveRecord::Base has_many :recipes, extend: HasManyProxyExtension::NameSearchableAndHumanizable endand the use case again:
Cook.first.recipes['cookie'].to_s => "Chocolate Chunk Cookies (30), Amish Cookies (60)"is still working with the advantage being able to reuse the module in another class:
class Recipe < ActiveRecord::Base has_many :ingredients, extend: HasManyProxyExtension::NameSearchableAndHumanizable def to_s "#{name} (#{time})" end end class Ingredient < ActiveRecord::Base def to_s return name if legal? "#{name} (illegal)" end endand its use case:
Recipe.first.ingredients['as'].to_s => "Basil, Sassafras (illegal)"Imagine, how the model classes would look like, if the logic could not be moved into a module.
Some times it is good choice to extend an association proxy with multiple modules:
module HasManyProxyExtension module NameSearchable def [] term where("#{proxy_association.klass.table_name}.name LIKE ?", "%#{term}%") end end module Humanizable def to_s map(&:to_s).join(', ') end end end class Cook < ActiveRecord::Base has_many :recipes, extend: [HasManyProxyExtension::NameSearchable, HasManyProxyExtension::Humanizable] endOf course it still works the same. But It allows deeper modularization and a more versatile combination of modules.
Further articles of interest:
Supported by Ruby 2.1.1 and Ruby on Rails 3.2.17
Keine Kommentare:
Kommentar veröffentlichen