Usage:
polymorphic :commentable do
belongs_to :post
belongs_to :comment
belongs_to :product
end
Adds validations that only one is set, and an accessor ('commentable' from above) that gets and sets the polymorphic relation.
Usage:
polymorphic :commentable do
belongs_to :post
belongs_to :comment
belongs_to :product
end
Adds validations that only one is set, and an accessor ('commentable' from above) that gets and sets the polymorphic relation.
module BetterPolymorphic | |
def polymorphic(polymorphic_name) | |
reflections_prior = self.reflections | |
yield | |
# Hash subtraction | |
new_reflections = (self.reflections.to_a - reflections_prior.to_a). | |
inject({}) {|acc, (k, v)| acc[k] = v; acc} | |
define_method polymorphic_name do | |
new_reflections.each_pair do |method, reflection| | |
return send(method) if send(reflection.foreign_key) | |
end | |
end | |
define_method "#{polymorphic_name}=" do |model| | |
new_reflections.each_pair do |method, reflection| | |
if model.is_a?(reflection.class_name.constantize) | |
return send("#{method}=", model) | |
end | |
end | |
end | |
define_method "validate_#{polymorphic_name}_belongs_to_one_model" do | |
if new_reflections.map(&:last).select {|r| send(r.foreign_key)}.size < 1 | |
errors.add(:base, 'must belong to a model') | |
end | |
end | |
private "validate_#{polymorphic_name}_belongs_to_one_model" | |
define_method "validate_#{polymorphic_name}_only_belongs_to_one_model" do | |
if new_reflections.map(&:last).select {|r| send(r.foreign_key) }.size > 1 | |
errors.add(:base, 'cannot belong to more than one model') | |
end | |
end | |
private "validate_#{polymorphic_name}_only_belongs_to_one_model" | |
validate "validate_#{polymorphic_name}_belongs_to_one_model" | |
validate "validate_#{polymorphic_name}_only_belongs_to_one_model" | |
end | |
end |