passive_record 0.4.14 → 0.4.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cacd9ce096b75a0cb189db566c1b506263462bcd
4
- data.tar.gz: 6d05d9c4520b4f8a7365ff587ee72e49fcb93f37
3
+ metadata.gz: 2e72e0564a1b8661c945d597f7419a24c9b00eb8
4
+ data.tar.gz: 1ff3f8c8430a145d19d6ea2c7c17e69a067a15b1
5
5
  SHA512:
6
- metadata.gz: 56634dcfa1edfa95df038ace1d9ea482b95a3d4766961dd802955cbd35f37311a3b97d2d97f93fc255fdafd248ce7dbae7fa867de964f4a6f2dfa950fd24331f
7
- data.tar.gz: 7aa8cec6e8442a4e9c7eb7a2cf1a72acd686028577b9604ef9ee373977a7deda2d8c3673fb6a9303eaaea713f0eae3289d18f06761afabd34d6cdbaf5bea6ba2
6
+ metadata.gz: 7f0fabaab580b4b110f49b16367f945180e8da5c5228d151caae2eb1bdbe9c85e8f85b2aab3d44fcb6136ac062d4a41d0e12f5699059b2b421484b14c1a30acd
7
+ data.tar.gz: 4d5cc36aa5a22c8a6573f7e653c5cfdfff04668ed3f150277f33546de1c3936bdab49e02886bdf979e63ca34e825c67c7363fffc834acb42dbfddb9086c12ffe
data/README.md CHANGED
@@ -44,6 +44,7 @@ PassiveRecord may be right for you!
44
44
  end
45
45
 
46
46
  class Dog < Model
47
+ attr_accessor :breed
47
48
  belongs_to :child
48
49
  end
49
50
 
@@ -64,26 +65,25 @@ PassiveRecord may be right for you!
64
65
  child = parent.create_child
65
66
  => Child (id: 1, dog_id: nil, parent_id: 1)
66
67
 
67
- dog = child.create_dog
68
- => Dog (id: 1, child_id: 1)
68
+ dog = child.create_dog(breed: "Pug")
69
+ => Dog (id: 1, child_id: 1, breed: "Pug")
69
70
 
70
71
  # Inverse relationships
71
72
  dog.child
72
- => Child (id: 1, dog_id: 1, parent_id: 1)
73
73
 
74
74
  Dog.find_by child: child
75
- => Dog (id: 1, child_id: 1)
75
+ => Dog (id: 1, child_id: 1, breed: "Pug")
76
76
 
77
77
  # Has many through
78
78
  parent.dogs
79
79
  => [ ...has_many :through relation... ]
80
80
 
81
81
  parent.dogs.all
82
- => [Dog (id: 1, child_id: 1)]
82
+ => [Dog (id: 1, child_id: 1, breed: "Pug")]
83
83
 
84
84
  # Nested queries
85
85
  Dog.find_all_by(child: { parent: parent })
86
- => [Dog (id: 1, child_id: 1)]
86
+ => [Dog (id: 1, child_id: 1, breed: "Pug")]
87
87
  ````
88
88
 
89
89
  ## PassiveRecord API
@@ -32,7 +32,7 @@ module PassiveRecord
32
32
  end
33
33
 
34
34
  define_method(parent_name_sym) do
35
- relation = relata.detect { |rel| rel.association == association }
35
+ relation = detect_relation(association)
36
36
  association.parent_class.find(relation.parent_model_id)
37
37
  end
38
38
 
@@ -41,7 +41,7 @@ module PassiveRecord
41
41
  end
42
42
 
43
43
  define_method(:"#{parent_name_sym}_id=") do |new_parent_id|
44
- relation = relata.detect { |rel| rel.association == association }
44
+ relation = detect_relation(association)
45
45
  relation.parent_model_id = new_parent_id
46
46
  end
47
47
  end
@@ -57,12 +57,12 @@ module PassiveRecord
57
57
  end
58
58
 
59
59
  define_method(child_name_sym) do
60
- relation = relata.detect { |rel| rel.association == association }
60
+ relation = detect_relation(association)
61
61
  relation.lookup
62
62
  end
63
63
 
64
64
  define_method(:"create_#{child_name_sym}") do |attrs={}|
65
- relation = relata.detect { |rel| rel.association == association }
65
+ relation = detect_relation(association)
66
66
  relation.create(attrs)
67
67
  end
68
68
 
@@ -71,7 +71,7 @@ module PassiveRecord
71
71
  end
72
72
 
73
73
  define_method(:"#{child_name_sym}_id=") do |new_child_id|
74
- relation = relata.detect { |rel| rel.association == association }
74
+ relation = detect_relation(association) #relata.detect { |rel| rel.association == association }
75
75
  rel = relation.lookup
76
76
  rel && rel.send(:"#{relation.parent_model_id_field}=", nil)
77
77
 
@@ -102,7 +102,7 @@ module PassiveRecord
102
102
  end
103
103
 
104
104
  define_method(:"#{collection_name_sym.to_s.singularize}_ids=") do |new_collection_ids|
105
- relation = relata.detect { |rel| rel.association == association }
105
+ relation = detect_relation(association) # relata.detect { |rel| rel.association == association }
106
106
 
107
107
  intermediary = relation.intermediary_relation
108
108
 
@@ -113,16 +113,16 @@ module PassiveRecord
113
113
 
114
114
  # add in new ones...
115
115
  singular_target = collection_name_sym.to_s.singularize
116
- if !(relation.nested_association.is_a?(BelongsToAssociation))# &&
116
+ if !(relation.nested_association.is_a?(BelongsToAssociation))
117
117
  intermediary.create(
118
118
  singular_target + "_ids" => new_collection_ids,
119
- relation.parent_model_id_field => relation.id
119
+ relation.parent_model_id_field => relation.id
120
120
  )
121
121
  else
122
122
  new_collection_ids.each do |child_id|
123
123
  intermediary.create(
124
- singular_target + "_id" => child_id,
125
- relation.parent_model_id_field => relation.id
124
+ singular_target + "_id" => child_id,
125
+ relation.parent_model_id_field => relation.id
126
126
  )
127
127
  end
128
128
  end
@@ -132,7 +132,7 @@ module PassiveRecord
132
132
  associate!(association)
133
133
 
134
134
  define_method(:"#{collection_name_sym}=") do |new_collection|
135
- relation = relata.detect { |rel| rel.association == association }
135
+ relation = detect_relation(association)
136
136
 
137
137
  # detach existing children...
138
138
  relation.all.each do |child|
@@ -146,21 +146,26 @@ module PassiveRecord
146
146
  end
147
147
 
148
148
  define_method(:"#{collection_name_sym.to_s.singularize}_ids=") do |new_collection_ids|
149
- relation = relata.detect { |rel| rel.association == association }
149
+ relation = detect_relation(association) #@ relata.detect { |rel| rel.association == association }
150
150
  send(:"#{collection_name_sym}=", relation.child_class.find(new_collection_ids))
151
151
  end
152
152
  end
153
153
 
154
154
  define_method(collection_name_sym) do
155
- relata.detect { |rel| rel.association == association }
155
+ detect_relation(association)
156
+ # relata.detect { |rel| rel.association == association }
156
157
  end
157
158
 
158
159
  define_method(:"#{collection_name_sym.to_s.singularize}_ids") do
159
- send(collection_name_sym).map(&:id)
160
+ begin
161
+ send(collection_name_sym).map(&:id)
162
+ rescue
163
+ binding.pry
164
+ end
160
165
  end
161
166
 
162
167
  define_method(:"create_#{collection_name_sym.to_s.singularize}") do |attrs={}|
163
- relation = relata.detect { |rel| rel.association == association }
168
+ relation = detect_relation(association) # relata.detect { |rel| rel.association == association }
164
169
  relation.create(attrs)
165
170
  end
166
171
  end
@@ -6,9 +6,11 @@ module PassiveRecord
6
6
  end
7
7
 
8
8
  def parent_class
9
- module_name = child_class.name.deconstantize
10
- module_name = "Object" if module_name.empty?
11
- (module_name.constantize).const_get(parent_class_name)
9
+ @parent_class ||= (
10
+ module_name = child_class.name.deconstantize
11
+ module_name = "Object" if module_name.empty?
12
+ (module_name.constantize).const_get(parent_class_name)
13
+ )
12
14
  end
13
15
 
14
16
  def child_class_name
@@ -4,11 +4,6 @@ module PassiveRecord
4
4
  def to_relation(parent_model)
5
5
  HasManyThroughRelation.new(self, parent_model)
6
6
  end
7
-
8
- def nested_association
9
- thru_klass = base_association.child_class_name.singularize.constantize
10
- thru_klass.associations.detect { |assn| assn.child_class_name == child_class_name }
11
- end
12
7
  end
13
8
 
14
9
  class HasManyThroughRelation < HasManyRelation
@@ -69,9 +64,9 @@ module PassiveRecord
69
64
  if intermediate_results && !join_results.empty?
70
65
  final_results = join_results.flat_map(&nested_association.target_name_symbol)
71
66
  if final_results.first.is_a?(Associations::Relation)
72
- final_results.flat_map(&:all)
67
+ final_results.flat_map(&:all).compact
73
68
  else
74
- Array(final_results)
69
+ Array(final_results.compact)
75
70
  end
76
71
  else
77
72
  []
@@ -90,61 +85,13 @@ module PassiveRecord
90
85
  end
91
86
  end
92
87
 
93
- def intermediary_conditions
94
- if intermediary_relation.is_a?(HasManyThroughRelation)
95
- conds = intermediary_relation.intermediary_conditions
96
-
97
- if nested_association.habtm || nested_association.is_a?(HasManyThroughAssociation)
98
- { association.through_class => conds }
99
- else
100
- { association.through_class.to_s.singularize.to_sym => conds }
101
- end
102
- elsif intermediary_relation.association.is_a?(HasManyAssociation) # normal has many?
103
- intermediary_key = if association.is_a?(HasManyThroughAssociation)
104
- ch = association.child_class_name.constantize
105
- inverse_assn = ch.associations.detect { |assn|
106
- if assn.is_a?(HasManyAssociation) || assn.is_a?(HasManyThroughAssociation)
107
- assn.child_class_name == association.base_association.child_class_name
108
- else # belongs to...
109
- assn.parent_class_name == association.base_association.child_class_name
110
- end
111
- }
112
-
113
- if inverse_assn.nil?
114
- association.through_class.to_s.singularize.to_sym
115
- elsif inverse_assn.is_a?(HasManyAssociation) || inverse_assn.is_a?(HasManyThroughAssociation)
116
- inverse_assn.children_name_sym
117
- else
118
- inverse_assn.target_name_symbol
119
- end
120
- elsif association.habtm
121
- association.base_association.children_name_sym
122
- else
123
- association.base_association.children_name_sym.to_s.singularize.to_sym
124
- end
125
-
126
- nested_conds = { intermediary_key => { parent_model_id_field.to_sym => parent_model.id } }
127
-
128
- if nested_association.is_a?(HasManyThroughAssociation)
129
- n = nested_association
130
- hash = nested_conds
131
-
132
- until !n.is_a?(HasManyThroughAssociation)
133
- key = n.through_class.to_s.singularize.to_sym
134
- hash = {key => hash}
135
- n = n.nested_association
136
- end
137
-
138
- hash
139
- else
140
- nested_conds
141
- end
142
- end
143
- end
144
-
145
88
  def where(conditions={})
146
- merged_conditions = conditions.merge(intermediary_conditions)
147
- child_class.where(merged_conditions)
89
+ Core::HasManyThroughQuery.new(
90
+ child_class,
91
+ parent_model,
92
+ association.target_name_symbol,
93
+ conditions
94
+ )
148
95
  end
149
96
  end
150
97
  end
@@ -40,9 +40,11 @@ module PassiveRecord
40
40
  end
41
41
 
42
42
  def child_class
43
- module_name = association.parent_class.name.deconstantize
44
- module_name = "Object" if module_name.empty?
45
- (module_name.constantize).const_get(association.child_class_name.singularize)
43
+ @child_class ||= (
44
+ module_name = association.parent_class.name.deconstantize
45
+ module_name = "Object" if module_name.empty?
46
+ (module_name.constantize).const_get(association.child_class_name.singularize)
47
+ )
46
48
  end
47
49
 
48
50
  def id
@@ -25,26 +25,30 @@ module PassiveRecord
25
25
  if @scope
26
26
  matching = @scope.method(:matching_instances)
27
27
  if negated?
28
- @klass.reject(&matching)
28
+ raw_all.reject(&matching)
29
29
  else
30
- @klass.select(&matching)
30
+ raw_all.select(&matching)
31
31
  end
32
32
  else
33
33
  matching = method(:matching_instances)
34
- @klass.select(&matching)
34
+ raw_all.select(&matching)
35
35
  end
36
36
  end
37
37
  def_delegators :all, :sample
38
38
 
39
+ def raw_all
40
+ @klass.all
41
+ end
42
+
39
43
  def each
40
44
  if @scope
41
45
  matching = @scope.method(:matching_instances)
42
46
  if negated?
43
- @klass.all.each do |instance|
47
+ raw_all.each do |instance|
44
48
  yield instance unless matching[instance]
45
49
  end
46
50
  else
47
- @klass.all.each do |instance|
51
+ raw_all.each do |instance|
48
52
  yield instance if matching[instance]
49
53
  end
50
54
  end
@@ -182,5 +186,18 @@ module PassiveRecord
182
186
  true
183
187
  end
184
188
  end
189
+
190
+ class HasManyThroughQuery < Query
191
+ def initialize(klass, instance, target_name_sym, conditions={})
192
+ @klass = klass
193
+ @instance = instance
194
+ @target_name_sym = target_name_sym
195
+ @conditions = conditions
196
+ end
197
+
198
+ def raw_all
199
+ @instance.send(@target_name_sym).all
200
+ end
201
+ end
185
202
  end
186
203
  end
@@ -52,6 +52,13 @@ module PassiveRecord
52
52
  []
53
53
  end
54
54
 
55
+ def detect_relation(assn)
56
+ @_associations ||= {}
57
+ @_associations[assn] ||= (
58
+ relata.detect { |rel| rel.association == assn }
59
+ )
60
+ end
61
+
55
62
  private
56
63
 
57
64
  def relata
@@ -1,4 +1,4 @@
1
1
  module PassiveRecord
2
2
  # passive_record version
3
- VERSION = "0.4.14"
3
+ VERSION = "0.4.15"
4
4
  end
@@ -288,64 +288,124 @@ describe "passive record models" do
288
288
  end
289
289
 
290
290
  context 'querying with scopes through relationships' do
291
- let!(:network) { Network.create }
292
- let!(:stream) { network.create_stream }
293
- let!(:channel) { stream.create_channel }
294
- let!(:feed) { channel.create_feed }
295
- let!(:a_blog) { feed.create_blog }
291
+ let(:network) { Network.create }
292
+ let(:stream) { network.create_stream }
293
+ let(:channel) { stream.create_channel }
294
+ let(:feed) { channel.create_feed }
295
+ let(:a_blog) { feed.create_blog }
296
+
296
297
  let!(:not_recent_post) { a_blog.create_post(published_at: 10.days.ago) }
297
298
  let!(:recent_post) do
298
299
  a_blog.create_post(published_at: 1.day.ago)
299
300
  end
300
301
 
302
+ let!(:special_category) { recent_post.create_category(special: true) }
303
+ let!(:unspecial_category) { recent_post.create_category(special: false) }
304
+
305
+ let!(:approved_comment) { recent_post.create_comment(approved: true) }
306
+ let!(:unapproved_comment) { recent_post.create_comment(approved: false) }
307
+
308
+ ###
309
+ #
310
+ let(:another_network) { Network.create }
311
+ let(:another_stream) { another_network.create_stream }
312
+ let(:another_channel) { another_stream.create_channel }
313
+ let(:another_feed) { another_channel.create_feed }
314
+ let(:another_blog) { another_feed.create_blog }
315
+
316
+
317
+ let!(:post_from_unrelated_blog) { another_blog.create_post(published_at: 1.day.ago) }
318
+ let!(:unrelated_comment) do
319
+ post_from_unrelated_blog.create_comment(approved: true)
320
+ end
321
+
322
+ let!(:another_category) do
323
+ post_from_unrelated_blog.create_category(special: true)
324
+ end
325
+
301
326
  describe 'should find related models through a has many' do
302
- it 'should restrict' do
327
+ it 'should refine' do
303
328
  expect(a_blog.posts.recent).to include(recent_post)
304
329
  expect(a_blog.posts.recent).not_to include(not_recent_post)
305
330
  end
331
+
332
+ it 'should restrict' do
333
+ a_blog.posts.all.each do |post|
334
+ expect(another_blog.posts.all.map(&:id)).not_to include(post.id)
335
+ end
336
+ end
306
337
  end
307
338
 
308
339
  describe 'should find related models on a has_many through' do
309
- it 'should restrict' do
340
+ it 'should refine' do
310
341
  expect(feed.posts.recent).to include(recent_post)
311
342
  expect(feed.posts.recent).not_to include(not_recent_post)
312
343
  end
344
+
345
+ it 'should restrict' do
346
+ feed.posts.each do |post|
347
+ expect(another_feed.posts).not_to include(post)
348
+ end
349
+ end
313
350
  end
314
351
 
315
352
  describe 'should find related models on a nested has_many thru' do
316
- it 'should restrict' do
353
+ it 'should refine' do
317
354
  expect(channel.posts.recent).to include(recent_post)
318
355
  expect(channel.posts.recent).not_to include(not_recent_post)
319
356
  end
357
+
358
+ it 'should restrict' do
359
+ channel.posts.each do |post|
360
+ expect(another_channel.posts).not_to include(post)
361
+ end
362
+ end
320
363
  end
321
364
 
322
365
  describe 'should find related models on a double-nested has_many thru' do
323
- it 'should restrict' do
366
+ it 'should refine' do
324
367
  expect(stream.posts.recent).to include(recent_post)
325
368
  expect(stream.posts.recent).not_to include(not_recent_post)
326
369
  end
370
+
371
+ it 'should restrict' do
372
+ expect(stream.posts.all).not_to be_empty
373
+ stream.posts.all.each do |post|
374
+ expect(another_stream.posts.all).not_to include(post)
375
+ end
376
+ end
327
377
  end
328
378
 
329
379
  describe 'should find related models on a deeply nested has_many thru' do
330
- it 'should restrict' do
380
+ it 'should refine' do
331
381
  expect(network.posts.recent).to include(recent_post)
332
382
  expect(network.posts.recent).not_to include(not_recent_post)
333
383
  end
384
+
385
+ it 'should restrict' do
386
+ network.posts.all.each do |post|
387
+ expect(another_network.posts.all.map(&:id)).not_to include(post.id)
388
+ end
389
+ end
334
390
  end
335
391
 
336
392
  describe 'should find related models on a recursive has_many thru' do
337
- let!(:approved_comment) { Post.first.create_comment(approved: true) }
338
- let!(:unapproved_comment) { Post.last.create_comment(approved: false) }
339
-
340
- it 'should refine/restrict' do
393
+ it 'should refine' do
341
394
  expect(network.comments.approved).to include(approved_comment)
342
395
  expect(network.comments.approved).not_to include(unapproved_comment)
343
396
  end
397
+
398
+ it 'should restrict' do
399
+ expect(network.comments.all).not_to be_empty
400
+ network.comments.all.each do |comment|
401
+ expect(another_network.comments).not_to include(comment)
402
+ end
403
+ end
344
404
  end
345
405
 
346
406
  describe 'should find related models a recursive has_many :thru a habtm' do
347
- let!(:promoted_tag) { Post.first.create_tag(promoted: true) }
348
- let!(:unpromoted_tag) { Post.last.create_tag(promoted: false) }
407
+ let!(:promoted_tag) { recent_post.create_tag(promoted: true) }
408
+ let!(:unpromoted_tag) { recent_post.create_tag(promoted: false) }
349
409
 
350
410
  it 'should refine and restrict' do
351
411
  expect(network.tags.promoted).to include(promoted_tag)
@@ -354,13 +414,19 @@ describe "passive record models" do
354
414
  end
355
415
 
356
416
  describe 'should find related nested models through a manual habtm' do
357
- let!(:special_category) { Post.first.create_category(special: true) }
358
- let!(:unspecial_category) { Post.last.create_category(special: false) }
359
417
 
360
- it 'should refine and restrict' do
418
+ it 'should refine' do
361
419
  expect(network.categories.special).to include(special_category)
362
420
  expect(network.categories.special).not_to include(unspecial_category)
363
421
  end
422
+
423
+ it 'should restrict' do
424
+ expect(another_network.categories.all).not_to be_empty
425
+ expect(network.categories.all).not_to be_empty
426
+ another_network.categories.where.all.each do |category|
427
+ expect(network.categories.where.all).not_to include(category)
428
+ end
429
+ end
364
430
  end
365
431
  end
366
432
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passive_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.14
4
+ version: 0.4.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Weissman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-19 00:00:00.000000000 Z
11
+ date: 2016-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport