passive_record 0.3.12 → 0.3.13
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.
- checksums.yaml +4 -4
- data/lib/passive_record/associations.rb +8 -3
- data/lib/passive_record/associations/belongs_to.rb +8 -1
- data/lib/passive_record/associations/has_many_through.rb +31 -31
- data/lib/passive_record/associations/has_one.rb +10 -6
- data/lib/passive_record/instance_methods.rb +1 -1
- data/lib/passive_record/version.rb +1 -1
- data/spec/passive_record_spec.rb +41 -38
- data/spec/spec_helper.rb +9 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de382da8a3a2ab040066d8602ae28c3949c53d63
|
4
|
+
data.tar.gz: 91c7c31efa8ba22d39dbe0197c6260b5021e48b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e90366ff1718151ab079032aa41755c40f1bfb68c8fcedc45f58804f26f728405b840d2e3a82043b92de2afdbb7a2fe21999bd099eaa41632941df77ee3e183
|
7
|
+
data.tar.gz: be96a58c45ac7cef2f498a6e0738ab4b1ed8f2119f904442a3c392a7cccb0be7b5e9661aa29db6df08c8042e437dbe76dc9fb72fe509dc290977e3b2e53e50b5
|
@@ -87,7 +87,7 @@ module PassiveRecord
|
|
87
87
|
through_class_collection_name = opts.delete(:through)
|
88
88
|
|
89
89
|
through_class_name = (through_class_collection_name.to_s).split('_').map(&:capitalize).join
|
90
|
-
base_association = associations.detect { |assn| assn.child_class_name == through_class_name }
|
90
|
+
base_association = associations.detect { |assn| assn.child_class_name == through_class_name rescue false }
|
91
91
|
|
92
92
|
association = HasManyThroughAssociation.new(
|
93
93
|
self, target_class_name, collection_name_sym, through_class_collection_name, base_association)
|
@@ -141,6 +141,7 @@ module PassiveRecord
|
|
141
141
|
|
142
142
|
define_method(:"create_#{collection_name_sym.to_s.singularize}") do |attrs={}|
|
143
143
|
relation = instance_eval{relata}.detect { |rel| rel.association == association }
|
144
|
+
# binding.pry
|
144
145
|
relation.create(attrs)
|
145
146
|
end
|
146
147
|
end
|
@@ -155,13 +156,17 @@ module PassiveRecord
|
|
155
156
|
self.name.split('::').last.singularize +
|
156
157
|
"JoinModel"
|
157
158
|
|
158
|
-
|
159
|
+
module_name = self.name.deconstantize
|
160
|
+
module_name = "Object" if module_name.empty?
|
161
|
+
intended_module = module_name.constantize
|
162
|
+
|
163
|
+
if (intended_module.const_get(inverse_habtm_join_class_name) rescue false)
|
159
164
|
has_many inverse_habtm_join_class_name.underscore.pluralize.to_sym
|
160
165
|
has_many collection_name_sym, :through => inverse_habtm_join_class_name.underscore.pluralize.to_sym
|
161
166
|
else
|
162
167
|
auto_collection_sym = self.name.split('::').last.underscore.pluralize.to_sym
|
163
168
|
eval <<-ruby
|
164
|
-
class ::#{habtm_join_class_name}
|
169
|
+
class #{module_name}::#{habtm_join_class_name} # class System::UserRoleJoinModel
|
165
170
|
include PassiveRecord # include PassiveRecord
|
166
171
|
belongs_to :#{collection_name_sym.to_s.singularize} # belongs_to :role
|
167
172
|
belongs_to :#{auto_collection_sym.to_s.singularize} # belongs_to :user
|
@@ -6,7 +6,14 @@ module PassiveRecord
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def parent_class
|
9
|
-
|
9
|
+
# look in same namespace as child 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
|
+
end
|
14
|
+
|
15
|
+
def child_class_name
|
16
|
+
child_class.name
|
10
17
|
end
|
11
18
|
end
|
12
19
|
|
@@ -9,14 +9,40 @@ module PassiveRecord
|
|
9
9
|
class HasManyThroughRelation < HasManyRelation
|
10
10
|
def <<(child)
|
11
11
|
intermediary_relation.
|
12
|
-
where(
|
12
|
+
where(
|
13
|
+
association.target_name_symbol.to_s.singularize + "_id" => child.id).
|
13
14
|
first_or_create
|
14
|
-
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(attrs={})
|
19
|
+
child = child_class.create(attrs)
|
20
|
+
send(:<<, child)
|
21
|
+
child
|
22
|
+
end
|
23
|
+
|
24
|
+
def nested_class
|
25
|
+
module_name = association.parent_class.name.deconstantize
|
26
|
+
module_name = "Object" if module_name.empty?
|
27
|
+
(module_name.constantize).
|
28
|
+
const_get("#{association.base_association.child_class_name.singularize}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def nested_association
|
32
|
+
nested_class.associations.detect { |assn|
|
33
|
+
assn.child_class_name == association.child_class_name ||
|
34
|
+
assn.child_class_name == association.child_class_name.singularize ||
|
35
|
+
|
36
|
+
(assn.parent_class_name == association.child_class_name rescue false) ||
|
37
|
+
(assn.parent_class_name == association.child_class_name.singularize rescue false) ||
|
38
|
+
|
39
|
+
assn.target_name_symbol == association.target_name_symbol.to_s.singularize.to_sym
|
40
|
+
}
|
15
41
|
end
|
16
42
|
|
17
43
|
def all
|
18
|
-
if
|
19
|
-
final_results =
|
44
|
+
if intermediate_results && !intermediate_results.empty?
|
45
|
+
final_results = intermediate_results.flat_map(&nested_association.target_name_symbol)
|
20
46
|
if final_results.first.is_a?(Associations::Relation) && !final_results.first.singular?
|
21
47
|
final_results.first.send(:all)
|
22
48
|
else
|
@@ -27,39 +53,13 @@ module PassiveRecord
|
|
27
53
|
end
|
28
54
|
end
|
29
55
|
|
30
|
-
|
31
56
|
def intermediary_relation
|
32
57
|
association.base_association.to_relation(parent_model)
|
33
58
|
end
|
34
59
|
|
35
|
-
def
|
60
|
+
def intermediate_results
|
36
61
|
intermediary_relation.all
|
37
62
|
end
|
38
|
-
|
39
|
-
def target_sym
|
40
|
-
name_str = association.target_name_symbol.to_s
|
41
|
-
singular_target_sym = name_str.singularize.to_sym
|
42
|
-
plural_target_sym = name_str.pluralize.to_sym
|
43
|
-
|
44
|
-
singular_class_name_sym = association.child_class_name.underscore.singularize.to_sym
|
45
|
-
plural_class_name_sym = association.child_class_name.underscore.pluralize.to_sym
|
46
|
-
|
47
|
-
if !results.empty?
|
48
|
-
if results.first.respond_to?(singular_target_sym)
|
49
|
-
singular_target_sym
|
50
|
-
elsif results.first.respond_to?(plural_target_sym)
|
51
|
-
plural_target_sym
|
52
|
-
elsif results.first.respond_to?(singular_class_name_sym)
|
53
|
-
singular_class_name_sym
|
54
|
-
elsif results.first.respond_to?(plural_class_name_sym)
|
55
|
-
plural_class_name_sym
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def create(attrs={})
|
61
|
-
child_class.create(attrs)
|
62
|
-
end
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -30,20 +30,24 @@ module PassiveRecord
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def parent_model_id_field
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def parent_class_name
|
37
|
-
association.parent_class.name.split('::').last.underscore
|
33
|
+
association.parent_class.name.demodulize.underscore + "_id"
|
38
34
|
end
|
39
35
|
|
40
36
|
def child_class
|
41
|
-
|
37
|
+
# look in same module as parent...
|
38
|
+
module_name = association.parent_class.name.deconstantize
|
39
|
+
module_name = "Object" if module_name.empty?
|
40
|
+
(module_name.constantize).
|
41
|
+
const_get(association.child_class_name.singularize)
|
42
42
|
end
|
43
43
|
|
44
44
|
def id
|
45
45
|
parent_model.id
|
46
46
|
end
|
47
|
+
|
48
|
+
def child_class_name
|
49
|
+
child_class.name
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
@@ -44,7 +44,7 @@ module PassiveRecord
|
|
44
44
|
attr_names = instance_variables
|
45
45
|
attr_names += self.class.associations_id_syms
|
46
46
|
attr_names += members rescue []
|
47
|
-
attr_names.reject! { |name| name.to_s.start_with?("@_") }
|
47
|
+
attr_names.reject! { |name| name.to_s.start_with?("@_") || name.match(/join_model/) }
|
48
48
|
attr_names - blacklisted_attribute_names
|
49
49
|
end
|
50
50
|
|
data/spec/passive_record_spec.rb
CHANGED
@@ -55,17 +55,17 @@ describe "passive record models" do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'should report relations' do
|
58
|
-
dog = Dog.create
|
58
|
+
dog = Family::Dog.create
|
59
59
|
expect(dog.inspect).
|
60
60
|
to eq("Family::Dog (id: #{dog.id.inspect}, breed: \"#{dog.breed}\", created_at: #{dog.created_at}, sound: \"bark\", child_id: nil)")
|
61
61
|
|
62
|
-
child = Child.create
|
62
|
+
child = Family::Child.create
|
63
63
|
child.dogs << dog
|
64
64
|
expect(dog.inspect).
|
65
65
|
to eq("Family::Dog (id: #{dog.id.inspect}, breed: \"#{dog.breed}\", created_at: #{dog.created_at}, sound: \"bark\", child_id: #{child.id.inspect})")
|
66
66
|
|
67
67
|
expect(child.inspect).
|
68
|
-
to eq("Family::Child (id: #{child.id.inspect}, created_at: #{child.created_at}, name: \"Alice\", toy_id: nil, dog_ids: [#{dog.id.inspect}], parent_id: nil)")
|
68
|
+
to eq("Family::Child (id: #{child.id.inspect}, created_at: #{child.created_at}, name: \"Alice\", toy_id: nil, dog_ids: [#{dog.id.inspect}], parent_id: nil, secret_club_ids: [])")
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -238,27 +238,27 @@ describe "passive record models" do
|
|
238
238
|
context 'hooks' do
|
239
239
|
context 'after create hooks' do
|
240
240
|
it 'should use a symbol to invoke a method' do
|
241
|
-
expect(Child.create.name).to eq("Alice")
|
241
|
+
expect(Family::Child.create.name).to eq("Alice")
|
242
242
|
end
|
243
243
|
|
244
244
|
it 'should use a block' do
|
245
|
-
expect(Dog.create.sound).to eq("bark")
|
245
|
+
expect(Family::Dog.create.sound).to eq("bark")
|
246
246
|
end
|
247
247
|
|
248
248
|
it 'should use an inherited block' do
|
249
|
-
expect(Parent.create.created_at).to be_a(Time)
|
249
|
+
expect(Family::Parent.create.created_at).to be_a(Time)
|
250
250
|
end
|
251
251
|
end
|
252
252
|
end
|
253
253
|
|
254
254
|
context 'associations' do
|
255
255
|
context 'one-to-one relationships' do
|
256
|
-
let(:child) { Child.create }
|
257
|
-
let(:another_child) { Child.create }
|
256
|
+
let(:child) { Family::Child.create }
|
257
|
+
let(:another_child) { Family::Child.create }
|
258
258
|
|
259
259
|
it 'should create children' do
|
260
|
-
expect { child.create_toy }.to change { Toy.count }.by(1)
|
261
|
-
expect(child.toy).to eq(Toy.last)
|
260
|
+
expect { child.create_toy }.to change { Family::Toy.count }.by(1)
|
261
|
+
expect(child.toy).to eq(Family::Toy.last)
|
262
262
|
end
|
263
263
|
|
264
264
|
it 'should have inverse relationships' do
|
@@ -270,23 +270,23 @@ describe "passive record models" do
|
|
270
270
|
end
|
271
271
|
|
272
272
|
it 'should assign parents' do
|
273
|
-
toy = Toy.create
|
273
|
+
toy = Family::Toy.create
|
274
274
|
toy.child = child
|
275
275
|
expect(child.toy).to eq(toy)
|
276
276
|
|
277
|
-
child.toy = Toy.create
|
277
|
+
child.toy = Family::Toy.create
|
278
278
|
expect(child.toy).not_to eq(toy)
|
279
279
|
end
|
280
280
|
end
|
281
281
|
|
282
282
|
context 'one-to-many relationships' do
|
283
|
-
let(:parent) { Parent.create }
|
284
|
-
let(:another_parent) { Parent.create(children: [another_child]) }
|
285
|
-
let(:another_child) { Child.create }
|
283
|
+
let(:parent) { Family::Parent.create }
|
284
|
+
let(:another_parent) { Family::Parent.create(children: [another_child]) }
|
285
|
+
let(:another_child) { Family::Child.create }
|
286
286
|
|
287
287
|
describe "#xxx<<" do
|
288
288
|
it 'should create children with <<' do
|
289
|
-
child = Child.create
|
289
|
+
child = Family::Child.create
|
290
290
|
expect {parent.children << child}.to change{parent.children.count}.by(1)
|
291
291
|
expect(parent.children).to include(child)
|
292
292
|
end
|
@@ -294,8 +294,8 @@ describe "passive record models" do
|
|
294
294
|
|
295
295
|
describe "#create_xxx" do
|
296
296
|
it 'should create children' do
|
297
|
-
expect { parent.create_child }.to change{ Child.count }.by(1)
|
298
|
-
expect(parent.children).to all(be_a(Child))
|
297
|
+
expect { parent.create_child }.to change{ Family::Child.count }.by(1)
|
298
|
+
expect(parent.children).to all(be_a(Family::Child))
|
299
299
|
end
|
300
300
|
end
|
301
301
|
|
@@ -317,32 +317,33 @@ describe "passive record models" do
|
|
317
317
|
end
|
318
318
|
|
319
319
|
context 'one-to-many through relationships' do
|
320
|
-
let(:parent) { Parent.create }
|
320
|
+
let(:parent) { Family::Parent.create }
|
321
321
|
let(:child) { parent.create_child }
|
322
322
|
|
323
323
|
it 'should collect children of children' do
|
324
324
|
child.create_dog(breed: 'mutt')
|
325
|
-
expect(parent.dogs.all).to all(be_a(Dog))
|
325
|
+
expect(parent.dogs.all).to all(be_a(Family::Dog))
|
326
326
|
expect(parent.dogs.count).to eq(1)
|
327
327
|
expect(parent.dogs.first).to eq(child.dogs.first)
|
328
328
|
expect(parent.dog_ids).to eq([child.dogs.first.id])
|
329
329
|
end
|
330
330
|
|
331
331
|
it 'should chain where clauses' do
|
332
|
-
child.create_dog(breed: 'mutt')
|
333
|
-
child.create_dog(breed: 'pit')
|
332
|
+
mutt = child.create_dog(breed: 'mutt')
|
333
|
+
pit = child.create_dog(breed: 'pit')
|
334
334
|
|
335
335
|
# another mutt, not the same childs
|
336
|
-
Dog.create(breed: 'mutt')
|
336
|
+
another_mutt = Family::Dog.create(breed: 'mutt')
|
337
337
|
|
338
|
-
expect(Dog.where(breed: 'mutt').
|
339
|
-
expect(child.dogs.where(breed: 'mutt').
|
338
|
+
expect(Family::Dog.where(breed: 'mutt').all).to eq([mutt, another_mutt])
|
339
|
+
expect(child.dogs.where(breed: 'mutt').all).to eq([mutt])
|
340
|
+
expect(child.dogs.where.not(breed: 'mutt').all).to eq([pit])
|
340
341
|
|
341
342
|
expect(
|
342
343
|
child.dogs.
|
343
344
|
where(breed: 'mutt')
|
344
345
|
).to eq(
|
345
|
-
Dog.
|
346
|
+
Family::Dog.
|
346
347
|
where(child_id: child.id).
|
347
348
|
where(breed: 'mutt')
|
348
349
|
)
|
@@ -350,27 +351,28 @@ describe "passive record models" do
|
|
350
351
|
|
351
352
|
it 'should do the nested query example from the readme' do
|
352
353
|
child.create_dog
|
353
|
-
expect(Dog.find_all_by(child: {parent: parent})).
|
354
|
+
expect(Family::Dog.find_all_by(child: {parent: parent})).
|
354
355
|
to eq(parent.dogs.all)
|
355
356
|
end
|
356
357
|
|
357
358
|
it 'should work for has-one intermediary relationships' do
|
358
359
|
child.create_toy
|
359
|
-
expect(parent.toys).to all(be_a(Toy))
|
360
|
+
expect(parent.toys).to all(be_a(Family::Toy))
|
360
361
|
expect(parent.toys.count).to eq(1)
|
361
362
|
expect(parent.toys.first).to eq(child.toy)
|
362
363
|
end
|
363
364
|
|
364
365
|
it 'should attempt to construct intermediary relations' do
|
365
|
-
expect { parent.create_toy(child: child) }.to change {Toy.count}.by(1)
|
366
|
-
expect(Toy.last.child).to eq(child)
|
367
|
-
expect(Toy.last.child.parent).to eq(parent)
|
366
|
+
expect { parent.create_toy(child: child) }.to change {Family::Toy.count}.by(1)
|
367
|
+
expect(Family::Toy.last.child).to eq(child)
|
368
|
+
expect(Family::Toy.last.child.parent).to eq(parent)
|
368
369
|
end
|
369
370
|
|
370
371
|
it 'should accept class name' do
|
371
372
|
post = Post.create
|
372
373
|
user = User.create
|
373
374
|
Comment.create(post: post, user: user)
|
375
|
+
|
374
376
|
expect(post.commenters.all).to eq([user])
|
375
377
|
end
|
376
378
|
end
|
@@ -422,14 +424,15 @@ describe "passive record models" do
|
|
422
424
|
it 'should handle inverse relations' do
|
423
425
|
expect {role.users << another_user}.to change{another_user.roles.count}.by(1)
|
424
426
|
end
|
425
|
-
end
|
426
|
-
end
|
427
|
-
end
|
428
427
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
428
|
+
it 'should work inside modules' do
|
429
|
+
child = Family::Child.create
|
430
|
+
secret_club = child.create_secret_club
|
431
|
+
|
432
|
+
expect(secret_club).to be_a(Family::SecretClub)
|
433
|
+
expect(secret_club.children.all).to eq([child])
|
434
|
+
expect(child.secret_clubs.first.create_child).to be_a(Family::Child)
|
435
|
+
end
|
433
436
|
end
|
434
437
|
end
|
435
438
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -36,6 +36,7 @@ module Family
|
|
36
36
|
has_one :toy
|
37
37
|
has_many :dogs
|
38
38
|
belongs_to :parent
|
39
|
+
has_and_belongs_to_many :secret_clubs
|
39
40
|
|
40
41
|
attr_reader :name
|
41
42
|
after_create :give_name
|
@@ -43,13 +44,17 @@ module Family
|
|
43
44
|
def give_name; @name = "Alice" end
|
44
45
|
end
|
45
46
|
|
47
|
+
class SecretClub < Model
|
48
|
+
has_and_belongs_to_many :children
|
49
|
+
end
|
50
|
+
|
46
51
|
class Parent < Model
|
47
52
|
has_many :children
|
48
53
|
has_many :dogs, :through => :children
|
49
54
|
has_many :toys, :through => :children
|
50
55
|
end
|
51
56
|
end
|
52
|
-
include Family
|
57
|
+
#include Family
|
53
58
|
|
54
59
|
###
|
55
60
|
|
@@ -90,18 +95,18 @@ end
|
|
90
95
|
###
|
91
96
|
|
92
97
|
class Post < Model
|
93
|
-
has_many :comments
|
98
|
+
has_many :comments
|
94
99
|
has_many :commenters, :through => :comments, :class_name => "User"
|
95
100
|
|
96
101
|
attr_accessor :published_at
|
97
102
|
before_create { @published_at = Time.now }
|
98
103
|
|
99
104
|
def self.recent
|
100
|
-
where(:published_at => 3.days.ago..Time.now)
|
105
|
+
where(:published_at => 3.days.ago..Time.now)
|
101
106
|
end
|
102
107
|
|
103
108
|
def self.published_within_days(n)
|
104
|
-
where(:published_at => n.days.ago..Time.now)
|
109
|
+
where(:published_at => n.days.ago..Time.now)
|
105
110
|
end
|
106
111
|
end
|
107
112
|
|