has_many_polymorphic 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,175 +1,144 @@
1
- module RussellEdge #:nodoc:
2
- module HasManyPolymorphic #:nodoc:
3
-
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
7
-
8
- module ClassMethods
9
-
10
- ##
11
- # HasManyPolymorphic
12
- # This mixin adds a has many polymorphic relationship to a model and creates all the relationships needed
13
- # by rails to handle it.
14
- #
15
- # Params
16
- #
17
- # Name - name of the relationship, there is a convention that whatever name you choose, the polymorphic
18
- # table columns on your through table should match.
19
- #
20
- # Options
21
- # - through - the model that handles the through relationship
22
- # - models - models that should be included in this polymophic relationship
23
- #
24
- #
25
- # One method is added for you to use
26
- #
27
- # - {name param}
28
- # - the name of your relationship is used for the method name of this method. it will return
29
- # an array of the models that are related via the has_many relationships
30
- #
31
- # There is an after_save call back that will save the relationships when they are added or removed
32
- # If you want to remove a relationship the models need to be destroyed and this model reloaded.
33
- #
34
- # Example Usage
35
- #
36
- # class PreferenceType < ActiveRecord::Base
37
- # has_morpheus :preferenced_records,
38
- # :through => :valid_preference_types,
39
- # :models => [:desktops, :organizers]
40
- # end
41
- #
42
- # this gives you the following
43
- #
44
- # preferenceType = PreferenceType.first
45
- # preferenceType.desktops
46
- # preferenceType.organizers
47
- #
48
- # and
49
- #
50
- # preferenceType.preferenced_records
51
- #
52
- # which is a concatentated array of the models. You also get the following
53
- #
54
- # desktop = Desktop.first
55
- # desktop.preference_types
56
- #
57
- # organizer = Organizer.first
58
- # organizer.preference_types
59
- ##
60
-
61
- def has_many_polymorphic(name, options = {})
62
- target_class_name = self.name
63
- instance_array_name = "#{name}_array".to_sym
64
-
65
- #declare array to related models
66
- attr_accessor instance_array_name
67
-
68
- #create the has_many relationship
69
- has_many options[:through], :dependent => :destroy
70
-
71
- #create the has_many relationship for each model
72
- options[:models].each do |model|
73
- has_many model, :through => options[:through], :source => model.to_s.singularize,
74
- :conditions => ["#{options[:through]}.#{name.to_s.singularize}_type = ?", model.to_s.classify], :dependent => :destroy
75
- end
76
-
77
- #modify the through class to add the belongs to relationships
78
- options[:through].to_s.classify.constantize.class_exec do
79
- options[:models].each do |model|
80
- belongs_to model.to_s.singularize.to_sym, :class_name => model.to_s.classify, :foreign_key => "#{name.to_s.singularize}_id"
81
- end
82
- end
83
-
84
- #I want to keep the << and push methods of array so this helps to keep them.
85
- define_method name do
86
- #used the declared instance variable array
87
- records = self.send(instance_array_name.to_s)
88
- records = records || []
89
- options[:models].each do |model|
90
- records = records | self.send(model.to_s)
91
- end
92
-
93
- #set it back to the instance variable
94
- self.send("#{instance_array_name.to_s}=", records)
95
-
96
- records
97
- end
98
-
99
- #before we save this model make sure you save all the relationships.
100
- before_save do |record|
101
- record.send(name).each do |reln_record|
102
- conditions = "#{name.to_s.singularize}_id = #{reln_record.id} and #{name.to_s.singularize}_type = '#{reln_record.class.name}'"
103
- exisiting_record = record.send("#{options[:through]}").find(:first,
104
- :conditions => conditions)
105
-
106
- if exisiting_record.nil?
107
- values_hash = {}
108
- values_hash["#{record.class.name.underscore}_id"] = record.id
109
- values_hash["#{name.to_s.singularize}_type"] = reln_record.class.name
110
- values_hash["#{name.to_s.singularize}_id"] = reln_record.id
111
-
112
- options[:through].to_s.classify.constantize.create(values_hash)
113
- end
114
- end
115
- end
116
-
117
- #include instance methods into this model
118
- include RussellEdge::HasManyPolymorphic::InstanceMethods
119
-
120
- #add the relationship to the models.
121
- options[:models].each do |model|
122
- model.to_s.classify.constantize.class_exec do
123
- #build the has many polymorphic relationship via finder_sql
124
- has_many options[:through], :as => name.to_s.singularize
125
- has_many target_class_name.tableize, :through => options[:through]
126
-
127
- #we want to save the relantionships when the model is saved
128
- before_save do |record|
129
- record.send(target_class_name.underscore.pluralize).each do |reln_record|
130
-
131
- db_result = ActiveRecord::Base.connection.select_all("SELECT count(*) as num_rows FROM #{options[:through]}
132
- where #{name.to_s.singularize}_id = #{record.id}
133
- and #{name.to_s.singularize}_type = '#{record.class.name}'
134
- and #{target_class_name.underscore.singularize}_id = #{reln_record.id}")
135
-
136
- #make sure that the relantionship does not already exist
137
- num_rows = db_result[0]['num_rows'] unless db_result == -1
138
- if num_rows.nil? || num_rows.to_i == 0
139
- values_hash = {}
140
- values_hash["#{reln_record.class.name.underscore}_id"] = reln_record.id
141
- values_hash["#{name.to_s.singularize}_type"] = record.class.name
142
- values_hash["#{name.to_s.singularize}_id"] = record.id
143
- options[:through].to_s.classify.constantize.create(values_hash)
144
- end
145
- end
146
- end
147
- end
148
-
149
- model.to_s.classify.constantize.class_eval do
150
- #check if this is using STI if so use the type attribute else use the class name
151
- def model_class_name
152
- if attributes['type']
153
- attributes['type']
154
- else
155
- self.class.to_s
156
- end
157
- end
158
- end
159
- end
160
-
161
- end
162
- end
163
-
164
- module InstanceMethods
165
- #clear array on reload
166
- def reload(*args)
167
- @records = []
168
-
169
- super args
170
- end
171
-
172
- end
173
-
174
- end
1
+ module RussellEdge #:nodoc:
2
+ module HasManyPolymorphic #:nodoc:
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ ##
11
+ # HasManyPolymorphic
12
+ # This mixin adds a has many polymorphic relationship to a model and creates all the relationships needed
13
+ # by rails to handle it.
14
+ #
15
+ # Params
16
+ #
17
+ # Name - name of the relationship, there is a convention that whatever name you choose, the polymorphic
18
+ # table columns on your through table should match.
19
+ #
20
+ # Options
21
+ # - through - the model that handles the through relationship
22
+ # - models - models that should be included in this polymophic relationship
23
+ #
24
+ #
25
+ # One method is added for you to use
26
+ #
27
+ # - {name param}
28
+ # - the name of your relationship is used for the method name of this method. it will return
29
+ # an array of the models that are related via the has_many relationships
30
+ #
31
+ # There is an after_save call back that will save the relationships when they are added or removed
32
+ # If you want to remove a relationship the models need to be destroyed and this model reloaded.
33
+ #
34
+ # Example Usage
35
+ #
36
+ # class PreferenceType < ActiveRecord::Base
37
+ # has_morpheus :preferenced_records,
38
+ # :through => :valid_preference_types,
39
+ # :models => [:desktops, :organizers]
40
+ # end
41
+ #
42
+ # this gives you the following
43
+ #
44
+ # preferenceType = PreferenceType.first
45
+ # preferenceType.desktops
46
+ # preferenceType.organizers
47
+ #
48
+ # and
49
+ #
50
+ # preferenceType.preferenced_records
51
+ #
52
+ # which is a concatentated array of the models. You also get the following
53
+ #
54
+ # desktop = Desktop.first
55
+ # desktop.preference_types
56
+ #
57
+ # organizer = Organizer.first
58
+ # organizer.preference_types
59
+ ##
60
+
61
+ def has_many_polymorphic(name, options = {})
62
+ target_class_name = self.name
63
+ instance_array_name = "#{name}_array".to_sym
64
+
65
+ #declare array to related models
66
+ attr_accessor instance_array_name
67
+
68
+ #create the has_many relationship
69
+ has_many options[:through], :dependent => :destroy
70
+
71
+ #create the has_many relationship for each model
72
+ options[:models].each do |model|
73
+ has_many model, :through => options[:through], :source => model.to_s.singularize,
74
+ :conditions => ["#{options[:through]}.#{name.to_s.singularize}_type = ?", model.to_s.classify], :dependent => :destroy
75
+ end
76
+
77
+ #modify the through class to add the belongs to relationships
78
+ options[:through].to_s.classify.constantize.class_exec do
79
+ options[:models].each do |model|
80
+ belongs_to model.to_s.singularize.to_sym, :class_name => model.to_s.classify, :foreign_key => "#{name.to_s.singularize}_id"
81
+ end
82
+ end
83
+
84
+ #I want to keep the << and push methods of array so this helps to keep them.
85
+ define_method name do
86
+ #used the declared instance variable array
87
+ records = self.send(instance_array_name.to_s)
88
+ records = records || []
89
+ options[:models].each do |model|
90
+ records = records | self.send(model.to_s)
91
+ end
92
+
93
+ #set it back to the instance variable
94
+ self.send("#{instance_array_name.to_s}=", records)
95
+
96
+ records
97
+ end
98
+
99
+ #before we save this model make sure you save all the relationships.
100
+ before_save do |record|
101
+ record.send(name).each do |reln_record|
102
+ conditions = "#{name.to_s.singularize}_id = #{reln_record.id} and #{name.to_s.singularize}_type = '#{reln_record.class.name}'"
103
+ exisiting_record = record.send("#{options[:through]}").find(:first,
104
+ :conditions => conditions)
105
+
106
+ #handle STI get superclass class_name if not sub class of ActiveRecord::Base
107
+ class_name = (reln_record.superclass == ActiveRecord::Base) ? reln_record.class.name : reln_record.superclass.class.name
108
+ if exisiting_record.nil?
109
+ values_hash = {}
110
+ values_hash["#{record.class.name.underscore}_id"] = record.id
111
+ values_hash["#{name.to_s.singularize}_type"] = reln_record.class.name
112
+ values_hash["#{name.to_s.singularize}_id"] = reln_record.id
113
+
114
+ options[:through].to_s.classify.constantize.create(values_hash)
115
+ end
116
+ end
117
+ end
118
+
119
+ #include instance methods into this model
120
+ include RussellEdge::HasManyPolymorphic::InstanceMethods
121
+
122
+ #add the relationship to the models.
123
+ options[:models].each do |model|
124
+ model.to_s.classify.constantize.class_exec do
125
+ has_many options[:through], :as => name.to_s.singularize
126
+ has_many target_class_name.tableize, :through => options[:through]
127
+ end
128
+ end
129
+
130
+ end
131
+ end
132
+
133
+ module InstanceMethods
134
+ #clear array on reload
135
+ def reload(*args)
136
+ @records = []
137
+
138
+ super args
139
+ end
140
+
141
+ end
142
+
143
+ end
175
144
  end
@@ -1,3 +1,3 @@
1
1
  module HasManyPolymorphic
2
- VERSION = '0.2.0' unless defined?(::HasManyPolymorphic::VERSION)
2
+ VERSION = '0.3.0' unless defined?(::HasManyPolymorphic::VERSION)
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_many_polymorphic
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Russell Holmes
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-09 00:00:00 Z
18
+ date: 2011-08-24 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activerecord