passive_record 0.1.5 → 0.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb29f6bd483e22725152cee6b4d3002d9ee6ef67
4
- data.tar.gz: 0a58e54140b5dd2a0d6adc19e446c6b10fe17a8a
3
+ metadata.gz: 1f29ddf4304ae896f01ee7455929a409966799df
4
+ data.tar.gz: cfa9db856459164c5864e4df1f2679cf2764a20f
5
5
  SHA512:
6
- metadata.gz: e943664cc21b10ab366ac8860cb6b6604ecd3ac2db51012043effc5c6f8aa73c80ccacbba4baba7aafc0cfd427f7a8a66e9243370fa982cff9caea19bba988b4
7
- data.tar.gz: 893747fcad8d5f3afab5fdb929a9f7015eabc82acbf28092badfc3b3057e5e4a48ad623e83c34bcea385890ba542c6d3cdf100a4ffd848bbb7dd1c4bf835f08a
6
+ metadata.gz: 0cb01f630b4bf056a4747a0f181afa3bd86859b663c831ef4f845d099d83078cc9fc20eef247ac3a08619fed9bc381996554409c113591cda491c9328817abbe
7
+ data.tar.gz: ae8db06335510ad6bb9213e4ce7c6024e85a02a979f0d4d718b1bea05de713a398488b74bd9d3dfdbe678857ad873c34d0c4b38397793c8347a9b98965300ff7
data/README.md CHANGED
@@ -36,6 +36,7 @@ PassiveRecord may be right for you!
36
36
 
37
37
  ## Examples
38
38
 
39
+ ````ruby
39
40
  require 'passive_record'
40
41
 
41
42
  class Model
@@ -58,20 +59,29 @@ PassiveRecord may be right for you!
58
59
 
59
60
  # Let's create some models!
60
61
  parent = Parent.create
62
+ => Parent (id: 1)
61
63
 
62
64
  child = parent.create_child
65
+ => Child (id: 1)
66
+
63
67
  dog = child.create_dog
68
+ => Dog (id: 1)
64
69
 
65
70
  # inverse relationships
66
- dog.child # ===> dog
71
+ dog.child
72
+ => Child (id: 1)
67
73
 
68
- Dog.find_by(child: child) # ===> dog
74
+ Dog.find_by child: child
75
+ => Dog (id: 1)
69
76
 
70
77
  # has many thru
71
- parent.dogs # ==> [dog]
78
+ parent.dogs
79
+ => [Dog (id: 1)]
72
80
 
73
81
  # nested queries
74
- Dog.find_all_by(child: { parent: parent }) # => [dog]
82
+ Dog.find_all_by(child: { parent: parent })
83
+ => [Dog (id: 1)]
84
+ ````
75
85
 
76
86
  ## Requirements
77
87
 
@@ -42,11 +42,15 @@ module PassiveRecord
42
42
 
43
43
  # from http://stackoverflow.com/a/8417341/90042
44
44
  def instance_variables_hash
45
- Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
45
+ Hash[
46
+ instance_variables.
47
+ reject { |sym| sym.to_s.start_with?("@_") }.
48
+ map { |name| [name, instance_variable_get(name)] }
49
+ ]
46
50
  end
47
51
 
48
52
  def relata
49
- @relata ||= self.class.associations.map do |assn|
53
+ @_relata ||= self.class.associations.map do |assn|
50
54
  assn.to_relation(self)
51
55
  end
52
56
  end
@@ -169,15 +173,15 @@ module PassiveRecord
169
173
  end
170
174
 
171
175
  protected
172
- def find_by_id(id)
173
- instances_by_id[id]
176
+ def find_by_id(_id)
177
+ key = instances_by_id.keys.detect { |id,_| id == _id }
178
+ instances_by_id[key] if key
174
179
  end
175
180
 
176
181
  def find_by_ids(ids)
177
182
  instances_by_id.select { |id,_| ids.include?(id) }.values
178
183
  end
179
184
 
180
-
181
185
  private
182
186
  def instances_by_id
183
187
  @instances ||= {}
@@ -23,7 +23,7 @@ module PassiveRecord
23
23
  end
24
24
 
25
25
  def has_many(collection_name_sym, opts={})
26
- target_class_name = (collection_name_sym.to_s).split('_').map(&:capitalize).join
26
+ target_class_name = opts.delete(:class_name) { (collection_name_sym.to_s).split('_').map(&:capitalize).join }
27
27
 
28
28
  if opts.key?(:through)
29
29
  through_class_collection_name = opts.delete(:through)
@@ -7,29 +7,45 @@ module PassiveRecord
7
7
  end
8
8
 
9
9
  class HasManyThroughRelation < HasManyRelation
10
- def lookup
11
- intermediate_results = association.base_association.
12
- to_relation(parent_model).
13
- lookup
10
+ def intermediary_relation
11
+ association.base_association.to_relation(parent_model)
12
+ end
14
13
 
15
- singular_target_sym = association.target_name_symbol.to_s.singularize.to_sym
16
- plural_target_sym = association.target_name_symbol.to_s.pluralize.to_sym
14
+ def results
15
+ intermediary_relation.lookup
16
+ end
17
17
 
18
- if !intermediate_results.empty?
19
- if intermediate_results.first.respond_to?(singular_target_sym)
20
- intermediate_results.flat_map(&singular_target_sym)
21
- elsif intermediate_results.first.respond_to?(plural_target_sym)
22
- intermediate_results.flat_map(&plural_target_sym)
23
- end
18
+ def lookup
19
+ if target_sym && results
20
+ results.flat_map(&target_sym)
24
21
  else
25
22
  []
26
23
  end
27
24
  end
28
25
 
26
+ def target_sym
27
+ name_str = association.target_name_symbol.to_s
28
+ singular_target_sym = name_str.singularize.to_sym
29
+ plural_target_sym = name_str.pluralize.to_sym
30
+
31
+ singular_class_name_sym = association.child_class_name.underscore.singularize.to_sym
32
+ plural_class_name_sym = association.child_class_name.underscore.pluralize.to_sym
33
+
34
+ if !results.empty?
35
+ if results.first.respond_to?(singular_target_sym)
36
+ singular_target_sym
37
+ elsif results.first.respond_to?(plural_target_sym)
38
+ plural_target_sym
39
+ elsif results.first.respond_to?(singular_class_name_sym)
40
+ singular_class_name_sym
41
+ elsif results.first.respond_to?(plural_class_name_sym)
42
+ plural_class_name_sym
43
+ end
44
+ end
45
+ end
46
+
29
47
  def create(attrs={})
30
- # binding.pry
31
- raise "missing intermediate relational key #{association.through_class}" unless attrs.key?(association.through_class)
32
- super(attrs)
48
+ child_class.create(attrs)
33
49
  end
34
50
  end
35
51
  end
@@ -33,6 +33,7 @@ module PassiveRecord
33
33
  end
34
34
 
35
35
  def child_class
36
+ # binding.pry
36
37
  Object.const_get(association.child_class_name.singularize)
37
38
  end
38
39
  end
@@ -6,7 +6,7 @@ module PassiveRecord
6
6
  end
7
7
 
8
8
  def ==(other_id)
9
- self.value == other_id.value
9
+ self.value == other_id.value rescue self.value == other_id
10
10
  end
11
11
 
12
12
  def inspect
@@ -1,4 +1,4 @@
1
1
  module PassiveRecord
2
2
  # passive_record version
3
- VERSION = "0.1.5"
3
+ VERSION = "0.1.6"
4
4
  end
@@ -35,22 +35,42 @@ describe Model do
35
35
  end
36
36
  end
37
37
 
38
- describe "#create" do
38
+ describe "#create" do
39
39
  it 'should assign attributes' do
40
40
  expect(model.foo).to eq('foo_value')
41
41
  end
42
42
  end
43
43
 
44
44
  describe "#destroy_all" do
45
- before {
46
- SimpleModel.create(foo: 'val')
47
- SimpleModel.create(foo: 'val')
45
+ before {
46
+ SimpleModel.create(foo: 'val1')
47
+ SimpleModel.create(foo: 'val2')
48
48
  }
49
+
49
50
  it 'should remove all models' do
50
51
  expect { SimpleModel.destroy_all }.to change { SimpleModel.count }.by(-SimpleModel.count)
51
52
  end
52
53
  end
53
54
 
55
+ context 'querying by id' do
56
+ describe "#find" do
57
+ subject(:model) { SimpleModel.create }
58
+ it 'should lookup a record based on an identifier' do
59
+ expect(SimpleModel.find(-1)).to eq(nil)
60
+ expect(SimpleModel.find(model.id)).to eq(model)
61
+ end
62
+
63
+ it 'should lookup records based on primary key value' do
64
+ expect(SimpleModel.find(model.id.value)).to eq(model)
65
+ end
66
+
67
+ it 'should lookup records based on ids' do
68
+ model_b = SimpleModel.create
69
+ expect(SimpleModel.find([model.id, model_b.id])).to eq([model, model_b])
70
+ end
71
+ end
72
+ end
73
+
54
74
  context 'querying by attributes' do
55
75
  describe "#find_by" do
56
76
  it 'should be retrievable by query' do
@@ -108,15 +128,15 @@ describe Model do
108
128
  let(:another_child) { Child.create }
109
129
 
110
130
  it 'should create children' do
111
- expect { child.create_dog }.to change { Dog.count }.by(1)
112
- expect(child.dogs.first).to eq(Dog.last)
131
+ expect { child.create_toy }.to change { Toy.count }.by(1)
132
+ expect(child.toy).to eq(Toy.last)
113
133
  end
114
134
 
115
135
  it 'should have inverse relationships' do
116
- dog = child.create_dog
117
- expect(dog.child).to eq(child)
118
- another_dog = another_child.create_dog
119
- expect(another_dog.child).to eq(another_child)
136
+ toy = child.create_toy
137
+ expect(toy.child).to eq(child)
138
+ another_toy = another_child.create_toy
139
+ expect(another_toy.child).to eq(another_child)
120
140
  end
121
141
  end
122
142
 
@@ -156,6 +176,26 @@ describe Model do
156
176
  expect(Dog.find_all_by(child: {parent: parent})).
157
177
  to eq(parent.dogs)
158
178
  end
179
+
180
+ it 'should work for has-one intermediary relationships' do
181
+ child.create_toy
182
+ expect(parent.toys).to all(be_a(Toy))
183
+ expect(parent.toys.count).to eq(1)
184
+ expect(parent.toys.first).to eq(child.toy)
185
+ end
186
+
187
+ it 'should attempt to construct intermediary relations' do
188
+ expect { parent.create_toy(child: child) }.to change {Toy.count}.by(1)
189
+ expect(Toy.last.child).to eq(child)
190
+ expect(Toy.last.child.parent).to eq(parent)
191
+ end
192
+
193
+ it 'should accept class name' do
194
+ post = Post.create
195
+ user = User.create
196
+ Comment.create(post: post, user: user)
197
+ expect(post.commenters).to eq([user])
198
+ end
159
199
  end
160
200
 
161
201
  context 'many-to-many' do
data/spec/spec_helper.rb CHANGED
@@ -21,7 +21,14 @@ class Dog < Model
21
21
  after_create {@sound = 'bark'}
22
22
  end
23
23
 
24
+ class Toy < Model
25
+ belongs_to :child
26
+ attr_reader :kind
27
+ after_create {@kind = %w[ stuffed_animal blocks cards ].sample}
28
+ end
29
+
24
30
  class Child < Model
31
+ has_one :toy
25
32
  has_many :dogs
26
33
  belongs_to :parent
27
34
 
@@ -34,6 +41,7 @@ end
34
41
  class Parent < Model
35
42
  has_many :children
36
43
  has_many :dogs, :through => :children
44
+ has_many :toys, :through => :children
37
45
  end
38
46
 
39
47
  ###
@@ -71,6 +79,7 @@ end
71
79
 
72
80
  class Post < Model
73
81
  has_many :comments
82
+ has_many :commenters, :through => :comments, :class_name => "User"
74
83
  end
75
84
 
76
85
  class User < Model
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passive_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Weissman