has_many_polymorphic 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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