acts_has_many 0.1.4 → 0.1.5

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.
data/README.md CHANGED
@@ -33,13 +33,13 @@ end
33
33
  # OR
34
34
 
35
35
  class Company < ActiveRecord::Base
36
- acts_has_many relations: [:users] # array necessary relations
36
+ acts_has_many :users # list necessary relations
37
37
 
38
38
  has_many :users
39
39
  end
40
40
 
41
41
  # acts_has_many options:
42
- # :relations( array; default: has many relation which are written above) - necessary relations
42
+ # list relations(it maybe missed if you use has many relation which are written above)
43
43
  # :compare( string or symbol; default: :title) - name column with unique elements in table
44
44
  # :through( boolean; default: false) - if you use has_many :through
45
45
 
@@ -60,9 +60,7 @@ company.actuale? :users # => false ( exclude 1 record of current relation)
60
60
 
61
61
  company # => <Company id: 1, title: "Microsoft">
62
62
 
63
- update_id, delete_id = company.has_many_update(data: { title: 'Google'}, relation: :users)
64
- # or
65
- # update_id, delete_id = company.has_many_update({ title: 'Google'}, :users)
63
+ update_id, delete_id = company.has_many_update({ title: 'Google'}, :users)
66
64
  # or
67
65
  # update_id, delete_id = company.update_with_users({ title: 'Google'})
68
66
 
@@ -213,4 +211,4 @@ features. Before submitting a bug report or feature request, check to make sure
213
211
  been submitted. You can indicate support for an existing issuse by voting it up. When submitting a
214
212
  bug report, please include a [Gist](http://gist.github.com/) that includes a stack trace and any
215
213
  details that may be necessary to reproduce the bug, including your gem version, Ruby version, and
216
- operating system. Ideally, a bug report should include a pull request with failing specs.
214
+ operating system. Ideally, a bug report should include a pull request with failing specs.
@@ -1,10 +1,10 @@
1
1
  module ActiveRecord
2
2
  module Acts #:nodoc:
3
3
  module HasMany
4
-
4
+
5
5
  # class methods for use in model
6
6
  # +acts_has_many_for+
7
- # +acts_has_many+
7
+ # +acts_has_many+
8
8
  #
9
9
  # the last method added:
10
10
  #
@@ -12,54 +12,54 @@ module ActiveRecord
12
12
  # +has_many_through_update+
13
13
  # +dependent_relations+
14
14
  # +compare+
15
- #
15
+ #
16
16
  # Instance methods:
17
17
  # +model+
18
- # +has_many_update+
18
+ # +has_many_update+
19
19
  # +has_many_update!+
20
20
  # +update_with_<relation>+
21
21
  # +actuale?+
22
22
  #
23
23
  # set +before_destroy+ callback;
24
24
 
25
- def self.included(base)
26
- base.extend(ClassMethods)
25
+ def self.included base
26
+ base.extend ClassMethods
27
27
  end
28
-
28
+
29
29
  #
30
- # Acts Has Many gem is for added functional to work
30
+ # Acts Has Many gem is for added functional to work
31
31
  # with +has_many+ relation (additional is has_many :trhough)
32
- #
32
+ #
33
33
  # +acts_has_many+ and +acts_has_many_for+ are class methods for all model,
34
34
  # and you can use them for connection acts_has_many functional to necessary model
35
- # acts_has_many set in model where is has_many relation and
35
+ # acts_has_many set in model where is has_many relation and
36
36
  # acts_has_many_for in model where use model with acts_has_many
37
37
  #
38
38
  # class Education < ActiveRecord::Base
39
39
  # belongs_to :location
40
- # ...
40
+ #
41
41
  # acts_has_many_for :location
42
42
  # end
43
- #
43
+ #
44
44
  # class Location < ActiveRecord::Base
45
45
  # has_many :educaitons
46
46
  # acts_has_many
47
47
  # end
48
- #
48
+ #
49
49
  # You can use +acts_has_many+ methods without +acts_has_many_for+
50
50
  #
51
51
  # class Education < ActiveRecord::Base
52
52
  # belongs_to :location
53
- # ...
53
+ #
54
54
  # end
55
- #
55
+ #
56
56
  # class Location < ActiveRecord::Base
57
57
  # has_many :education
58
58
  # acts_has_many
59
59
  # end
60
- #
60
+ #
61
61
  # in this case you can use nex function:
62
- #
62
+ #
63
63
  # education = Education.first
64
64
  # location = education.location # get location from education
65
65
  #
@@ -68,7 +68,7 @@ module ActiveRecord
68
68
  # new_id, del_id = location.has_many_update({title:"Kyiv"}, :educations)
69
69
  # # or with dinamic methods helper
70
70
  # new_id, del_id = location.update_with_educations {title:"Kyiv"}
71
- #
71
+ #
72
72
  # # you can also use has_many_update! which updated relation with parent row without you
73
73
  # location.has_many_update!({title: "Kyiv"}, education)
74
74
  #
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
  # # and
81
81
  # location.has_many_update! {title:"Kyiv"}
82
82
  #
83
-
83
+
84
84
  module ClassMethods
85
85
 
86
86
  #
@@ -88,23 +88,29 @@ module ActiveRecord
88
88
  # use for set link between parent row and child
89
89
  # options: list relations (symbol)
90
90
  #
91
-
92
- def acts_has_many_for(*relations)
91
+
92
+ def acts_has_many_for *relations
93
93
  relations.each do |relation|
94
94
  relation = relation.to_s
95
95
  class_eval <<-EOV
96
96
  def #{relation}
97
- row = #{relation.classify}.find #{relation.foreign_key}
98
- row.tmp_parrent_id = id
99
- row.tmp_current_relation = '#{self.name.tableize}'
100
- row
97
+ if #{relation.foreign_key}
98
+ row = #{relation.classify}.find #{relation.foreign_key}
99
+ if row.is_a? #{relation.classify}
100
+ row.tmp_parrent_id = id
101
+ row.tmp_current_relation = '#{self.name.tableize}'
102
+ end
103
+ row
104
+ else
105
+ super
106
+ end
101
107
  end
102
108
  EOV
103
109
  end
104
110
  end
105
111
 
106
112
  #
107
- # +acts_has_many+ - available method in all model and switch on
113
+ # +acts_has_many+ - available method in all model and switch on
108
114
  # extension functional in concrete model (need located this method
109
115
  # after relation which include in dependence, or anywhere but set depend relation)
110
116
  # options
@@ -112,23 +118,31 @@ module ActiveRecord
112
118
  # :relations( array) - concrete name of depended relation
113
119
  # :through( boolean) - off or on has_many_through_update method
114
120
  #
115
-
116
- def acts_has_many(options = {})
117
- dependent_relations = []
118
- options_default = { compare: :title, through: false }
119
121
 
120
- options = options_default.merge options
121
-
122
+ def acts_has_many *opt
123
+ options = { compare: :title, through: false }
124
+ options.update opt.extract_options!
125
+ options.assert_valid_keys :compare, :through, :relations
126
+ if options[:relations]
127
+ ActiveSupport::Deprecation.warn "Use simple list relations insted 'relation: Array'! Parameter 'relation: []' will be romoved in v1.0!"
128
+ end
129
+ options[:relations] ||= opt
130
+
122
131
  options[:relations] = self.reflect_on_all_associations(:has_many)
123
- .map{|o| o.name} if options[:relations].nil?
124
-
132
+ .map(&:name) if options[:relations].blank?
133
+
134
+ dependent_relations = []
125
135
  options[:relations].each do |relation|
126
- dependent_relations << relation.to_s.tableize
136
+ if reflect_on_association relation.to_sym
137
+ dependent_relations << relation.to_s.tableize
138
+ else
139
+ raise ArgumentError, "No association found for name `#{relation}'. Has it been defined yet?"
140
+ end
127
141
  end
128
-
142
+
129
143
  #
130
- # +has_many_through_update+ (return array) [ 1 - array objects records, 2 - array delete ids ]
131
- # options
144
+ # +has_many_through_update+ (return array) [ 1 - array objects records, 2 - array delete ids ]
145
+ # options
132
146
  # :update( array) - data for update (id and data)
133
147
  # :new( array) - data for create record (data)
134
148
  #
@@ -136,20 +150,19 @@ module ActiveRecord
136
150
  #
137
151
 
138
152
  has_many_through = ''
139
- if(options[:through])
153
+ if options[:through]
140
154
  has_many_through = """
141
155
  def self.has_many_through_update(options)
142
156
  record_add = []
143
157
  record_del = []
144
-
158
+
145
159
  # update
146
160
  options[:update].each do |id, data|
147
- add, del = #{self}.find(id)
148
- .has_many_update(:data => data, :relation => options[:relation])
161
+ add, del = #{self}.find(id).has_many_update data, options[:relation]
149
162
  record_add << add unless add.nil?
150
163
  record_del << del unless del.nil?
151
164
  end unless options[:update].nil?
152
-
165
+
153
166
  # new
154
167
  unless options[:new].nil?
155
168
  options[:new].uniq!
@@ -159,25 +172,25 @@ module ActiveRecord
159
172
  .where('#{options[:compare]}' => data['#{options[:compare]}'.to_sym])
160
173
  .first_or_create(data)
161
174
  record_del.delete record_add.last.id
162
- end
175
+ end
163
176
  end
164
-
165
- record_add = #{self}.where('id IN (?)', record_add) unless record_add.empty?
177
+
178
+ record_add = #{self}.where('id IN (?)', record_add) unless record_add.empty?
166
179
  [record_add, record_del]
167
180
  end """
168
181
  end
169
-
182
+
170
183
  # add dinamic methods for example
171
184
  # update_with_<relation>(data) equal has_many_update(data, relation)
172
185
  extend_methods = ''
173
186
  dependent_relations.each do |relation|
174
187
  extend_methods += """
175
188
  def update_with_#{relation}(data)
176
- has_many_update data: data, relation: :#{relation}
189
+ has_many_update data, :#{relation}
177
190
  end
178
191
  """
179
192
  end
180
-
193
+
181
194
  class_eval <<-EOV
182
195
  include ActiveRecord::Acts::HasMany::InstanceMethods
183
196
  class << self
@@ -191,96 +204,97 @@ module ActiveRecord
191
204
 
192
205
  def model
193
206
  #{self}
194
- end
195
-
207
+ end
208
+
196
209
  #{extend_methods}
197
210
  #{has_many_through}
198
-
211
+
199
212
  attr_accessor :tmp_current_relation, :tmp_parrent_id
213
+ validates :#{options[:compare]}, uniqueness: true, presence: true
200
214
  before_destroy :destroy_filter
201
215
  EOV
202
216
  end
203
217
  end
204
-
218
+
205
219
  module InstanceMethods
206
-
220
+
207
221
  #
208
- # +has_many_update!+ identicaly to has_many_update but
222
+ # +has_many_update!+ identicaly to has_many_update but
209
223
  # You can use this method when you use +acts_has_many_for+
210
224
  # and get object for update with help of +relation+ or give parent row
211
225
  # option
212
- # data for update
213
- # parrent row (maybe miss)
226
+ # data - date for update
227
+ # obj - parrent row (maybe miss)
214
228
  #
215
229
 
216
- def has_many_update!(*data)
230
+ def has_many_update! *data
217
231
  if data.size == 2
218
232
  self.tmp_current_relation = data[1].class.name.tableize
219
233
  self.tmp_parrent_id = data[1].id
220
234
  end
221
-
235
+
222
236
  if tmp_current_relation.nil? or tmp_parrent_id.nil?
223
- p "ArgumentError: 'has_many_update!' don't have data about parent object"
224
- p "* maybe you use 'acts_has_many_for' incorrectly"
225
- p "* if you don't use 'acts_has_many_for' in parent model you can give parent object"
226
- return nil
237
+ raise ArgumentError, """has_many_update don't have data about parent object,
238
+ * maybe you use 'acts_has_many_for' incorrectly,
239
+ * if you don't use 'acts_has_many_for' in parent model you can give parent object"""
227
240
  end
228
241
 
229
242
  new_id, del_id = has_many_update data[0]
230
- parrent = eval(tmp_current_relation.classify).find(tmp_parrent_id)
243
+ parrent = eval(tmp_current_relation.classify).find tmp_parrent_id
231
244
  parrent.update_attributes("#{model.name.foreign_key}" => new_id)
232
245
  parrent.save!
233
246
 
234
247
  destroy unless del_id.nil?
235
248
  model.find new_id
236
249
  end
237
-
250
+
238
251
  #
239
- # +has_many_update+ ( return array) [new_id, del_id]
252
+ # +has_many_update+ ( return array) [new_id, remove_id]
240
253
  # options maybe Hash, or list parameters
241
- # :data( type: hash) - data for updte
242
- # :relation( type: str, symbol) - modifi with tableize (maybe miss)
243
- #
244
-
245
- def has_many_update(*options)
246
- if options.size == 1 && options[0].include?(:data) && options[0].include?(:relation)
247
- data = options[0][:data]
248
- relation = options[0][:relation]
254
+ # data ( type: hash) - data for updte
255
+ # relation( type: str, symbol) - modifi with tableize (maybe miss)
256
+ #
257
+
258
+ def has_many_update *options
259
+ if options.size == 1 && options.first.include?(:data) && options[0].include?(:relation)
260
+ data = options.first[:data]
261
+ relation = options.first[:relation]
262
+ ActiveSupport::Deprecation.warn "Use simple list parameters (data, relation), parameter with 'Hash' type will be romoved in v1.0!"
249
263
  elsif options.size == 2
250
- data = options[0]
264
+ data = options.first
251
265
  relation = options[1]
252
266
  else
253
267
  relation = tmp_current_relation
254
- data = options[0]
268
+ data = options.first
255
269
  end
256
-
257
- data_default = {}
258
- data_default[model.compare] = ""
259
- data = data_default.merge data
270
+
271
+ data = { model.compare => ''}.merge data
260
272
 
261
273
  if relation.blank?
262
- p "Notice: 'has_many_update' don't know about current relation, and check all relations"
274
+ warn "[ARRGUMENT MISSING]: 'has_many_update' don't know about current relation, and check all relations"
263
275
  end
264
-
276
+
265
277
  has_many_cleaner data.symbolize_keys, relation
266
278
  end
267
-
279
+
268
280
  #
269
281
  # +actuale?+ - check the acutuality of element in has_many table
270
- # options maybe Hash, or simple parameter
271
- # :relation( string, symbol) - exclude current relation (maybe miss)
282
+ # options:
283
+ # relation (String, Symbol) - for exclude current relation
272
284
  #
273
-
274
- def actuale? (options={relation: ""})
275
- if options.is_a? Hash and options.include? :relation
276
- relation = options[:relation].to_s.tableize
285
+
286
+ def actuale? opt={relation: ""}
287
+ if opt.is_a? Hash
288
+ opt.assert_valid_keys :relation
289
+ ActiveSupport::Deprecation.warn "Use simple parameter 'String' or 'Symbol', parameter with 'Hash' type will be romoved in v1.0!"
290
+ relation = opt[:relation].to_s.tableize
277
291
  else
278
- relation = options.to_s.tableize
292
+ relation = opt.to_s.tableize
279
293
  end
280
294
 
281
295
  actuale = false
282
296
  model.dependent_relations.each do |dependent_relation|
283
- tmp = self.send(dependent_relation)
297
+ tmp = self.send dependent_relation
284
298
  if relation == dependent_relation
285
299
  actuale ||= tmp.all.size > 1
286
300
  else
@@ -290,9 +304,9 @@ module ActiveRecord
290
304
  actuale
291
305
  end
292
306
  end
293
-
307
+
294
308
  private
295
-
309
+
296
310
  #
297
311
  # +destroy_filter+ - method for before_destroy, check actuale record and
298
312
  # return true for delete or false for leave
@@ -302,22 +316,22 @@ module ActiveRecord
302
316
  not actuale?
303
317
  end
304
318
 
305
- #
319
+ #
306
320
  # base operations in this gem
307
321
  #
308
322
 
309
- def has_many_cleaner(data, relation)
323
+ def has_many_cleaner data, relation
310
324
  compare = { model.compare => data[model.compare] }
311
-
325
+
312
326
  object_id = id
313
327
  delete_id = nil
314
-
328
+
315
329
  if actuale? relation
316
330
  # create new object and finish
317
- object = model.where(compare).first_or_create(data)
331
+ object = model.where(compare).first_or_create data
318
332
  object_id = object.id
319
333
  else
320
- object_tmp = model.where(compare)[0]
334
+ object_tmp = model.where(compare).first
321
335
  unless object_tmp.nil?
322
336
  # set new object and delete old
323
337
  delete_id = (object_id == object_tmp.id) ? nil : object_id
@@ -325,14 +339,14 @@ module ActiveRecord
325
339
  else
326
340
  # update old object
327
341
  if object_id.nil?
328
- object = model.where(compare).first_or_create(data)
342
+ object = model.where(compare).first_or_create data
329
343
  object_id = object.id
330
344
  else
331
345
  if data[model.compare].blank?
332
346
  delete_id = object_id
333
347
  object_id = nil
334
348
  else
335
- update_attributes(data)
349
+ update_attributes data
336
350
  end
337
351
  end
338
352
  end
@@ -1,3 +1,3 @@
1
1
  module ActsHasMany
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_has_many
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-29 00:00:00.000000000 Z
12
+ date: 2012-10-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -113,9 +113,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  version: '0'
114
114
  requirements: []
115
115
  rubyforge_project:
116
- rubygems_version: 1.8.19
116
+ rubygems_version: 1.8.24
117
117
  signing_key:
118
118
  specification_version: 3
119
119
  summary: All records must be used, otherwise they will be deleted. Clear logic with
120
120
  has_many
121
- test_files: []
121
+ test_files:
122
+ - spec/has_many_spec.rb
123
+ - spec/has_many_through_spec.rb
124
+ - spec/helper.rb