Module: RussellEdge::HasManyPolymorphic::ClassMethods
- Defined in:
- lib/has_many_polymorphic/has_many_polymorphic.rb
Instance Method Summary collapse
-
#has_many_polymorphic(name, options = {}) ⇒ Object
HasManyPolymorphic This mixin adds a has many polymorphic relationship to a model and creates all the relationships needed by rails to handle it.
Instance Method Details
#has_many_polymorphic(name, options = {}) ⇒ Object
HasManyPolymorphic
This mixin adds a has many polymorphic relationship to a model and creates all the relationships needed
by rails to handle it.
Params
Name - name of the relationship, there is a convention that whatever name you choose, the polymorphic
table columns on your through table should match.
Options
- through - the model that handles the through relationship
- models - models that should be included in this polymophic relationship
One method is added for you to use
- {name param}
- the name of your relationship is used for the method name of this method. it will return
an array of the models that are related via the has_many relationships
There is an after_save call back that will save the relationships when they are added or removed
If you want to remove a relationship the models need to be destroyed and this model reloaded.
Example Usage
class PreferenceType < ActiveRecord::Base
has_many_polymorphic :preferenced_records,
:through => :valid_preference_types,
:models => [:desktops, :organizers]
end
this gives you the following
preferenceType = PreferenceType.first
preferenceType.desktops
preferenceType.organizers
and
preferenceType.preferenced_records
which is a concatentated array of the models. You also get the following
desktop = Desktop.first
desktop.preference_types
organizer = Organizer.first
organizer.preference_types
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/has_many_polymorphic/has_many_polymorphic.rb', line 61 def has_many_polymorphic(name, = {}) target_class_name = self.name instance_array_name = "#{name}_array".to_sym #declare array to related models attr_accessor instance_array_name #create the has_many relationship has_many [:through], :dependent => :destroy #create the has_many relationship for each model [:models].each do |model| has_many model.to_sym, -> { where("#{[:through]}.#{name.to_s.singularize}_type = ?", model.to_s.classify) }, :through => [:through], :source => model.to_s.singularize, :dependent => :destroy end #modify the through class to add the belongs to relationships [:through].to_s.classify.constantize.class_exec do [:models].each do |model| belongs_to model.to_s.singularize.to_sym, :class_name => model.to_s.classify, :foreign_key => "#{name.to_s.singularize}_id" end end #I want to keep the << and push methods of array so this helps to keep them. define_method name do #used the declared instance variable array records = self.send(instance_array_name.to_s) records = records || [] [:models].each do |model| records = records | self.send(model.to_s) end #set it back to the instance variable self.send("#{instance_array_name.to_s}=", records) records end #before we save this model make sure you save all the relationships. before_save do |record| record.send(name).each do |reln_record| #handle STI get superclass class_name if not sub class of ActiveRecord::Base klass_name = (reln_record.class.superclass == ::ApplicationRecord) ? reln_record.class.name : reln_record.class.superclass.name conditions = "#{name.to_s.singularize}_id = #{reln_record.id} and #{name.to_s.singularize}_type = '#{klass_name}'" exisiting_record = record.send("#{[:through]}").where(conditions).first if exisiting_record.nil? values_hash = {} values_hash["#{record.class.name.underscore}_id"] = record.id values_hash["#{name.to_s.singularize}_type"] = klass_name values_hash["#{name.to_s.singularize}_id"] = reln_record.id [:through].to_s.classify.constantize.create(values_hash) end end end #add the relationship to the models. [:models].each do |model| model.to_s.classify.constantize.class_exec do has_many [:through], :as => name.to_s.singularize, :dependent => :destroy has_many target_class_name.tableize.to_sym, :through => [:through], :dependent => :destroy end end end |