passive_record 0.1.5 → 0.1.6

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: 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