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 |