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
end
and 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
end
and 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
end
and 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]
end
Of 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