ninja-model 0.8.1 → 0.9.0
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/.gitignore +1 -1
- data/Gemfile +1 -0
- data/Rakefile +6 -0
- data/lib/ninja_model.rb +23 -7
- data/lib/ninja_model/adapters.rb +25 -20
- data/lib/ninja_model/adapters/adapter_manager.rb +2 -0
- data/lib/ninja_model/adapters/adapter_pool.rb +2 -0
- data/lib/ninja_model/associations.rb +63 -101
- data/lib/ninja_model/associations/association.rb +146 -0
- data/lib/ninja_model/associations/association_scope.rb +39 -0
- data/lib/ninja_model/associations/belongs_to_association.rb +33 -21
- data/lib/ninja_model/associations/builder/association.rb +57 -0
- data/lib/ninja_model/associations/builder/belongs_to.rb +33 -0
- data/lib/ninja_model/associations/builder/collection_association.rb +60 -0
- data/lib/ninja_model/associations/builder/has_many.rb +11 -0
- data/lib/ninja_model/associations/builder/has_one.rb +20 -0
- data/lib/ninja_model/associations/builder/singular_association.rb +49 -0
- data/lib/ninja_model/associations/collection_association.rb +103 -0
- data/lib/ninja_model/associations/collection_proxy.rb +45 -0
- data/lib/ninja_model/associations/has_many_association.rb +19 -43
- data/lib/ninja_model/associations/has_one_association.rb +52 -6
- data/lib/ninja_model/associations/singular_association.rb +61 -0
- data/lib/ninja_model/attribute.rb +5 -2
- data/lib/ninja_model/attribute_methods.rb +35 -40
- data/lib/ninja_model/base.rb +31 -39
- data/lib/ninja_model/identity.rb +8 -6
- data/lib/ninja_model/rails_ext/active_record.rb +69 -225
- data/lib/ninja_model/railtie.rb +0 -9
- data/lib/ninja_model/reflection.rb +103 -20
- data/lib/ninja_model/relation.rb +2 -2
- data/lib/ninja_model/relation/query_methods.rb +16 -0
- data/lib/ninja_model/version.rb +1 -1
- data/ninja-model.gemspec +2 -1
- data/spec/db/schema.rb +15 -0
- data/spec/{ninja_model → lib/ninja_model}/adapters/abstract_adapter_spec.rb +0 -0
- data/spec/lib/ninja_model/adapters/adapter_manager_spec.rb +72 -0
- data/spec/lib/ninja_model/adapters/adapter_pool_spec.rb +230 -0
- data/spec/lib/ninja_model/adapters_spec.rb +120 -0
- data/spec/lib/ninja_model/associations/belongs_to_association_spec.rb +76 -0
- data/spec/lib/ninja_model/associations/has_many_association_spec.rb +118 -0
- data/spec/lib/ninja_model/associations/has_one_association_spec.rb +80 -0
- data/spec/{ninja_model → lib/ninja_model}/attribute_methods_spec.rb +2 -2
- data/spec/{ninja_model → lib/ninja_model}/attribute_spec.rb +4 -0
- data/spec/{ninja_model → lib/ninja_model}/base_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/identity_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/persistence_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/predicate_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/query_methods_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/reflection_spec.rb +7 -9
- data/spec/{ninja_model → lib/ninja_model}/relation_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/symbol_spec.rb +0 -0
- data/spec/{ninja_model → lib/ninja_model}/validation_spec.rb +0 -0
- data/spec/{ninja_model_spec.rb → lib/ninja_model_spec.rb} +0 -0
- data/spec/models/bio.rb +8 -0
- data/spec/models/body.rb +7 -0
- data/spec/models/category.rb +7 -0
- data/spec/models/email_address.rb +3 -0
- data/spec/models/post.rb +13 -0
- data/spec/models/tag.rb +3 -0
- data/spec/models/user.rb +4 -0
- data/spec/spec_helper.rb +38 -5
- data/spec/support/dummy_adapter/adapter.rb +48 -0
- data/spec/support/factories/bio.rb +11 -0
- data/spec/support/factories/body.rb +12 -0
- data/spec/support/factories/email_address.rb +5 -0
- data/spec/support/factories/post.rb +12 -0
- data/spec/support/factories/tag.rb +5 -0
- data/spec/support/factories/user.rb +5 -0
- metadata +121 -63
- data/spec/ninja_model/adapters/adapter_manager_spec.rb +0 -69
- data/spec/ninja_model/adapters/adapter_pool_spec.rb +0 -230
- data/spec/ninja_model/adapters_spec.rb +0 -85
@@ -1,230 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe NinjaModel::Adapters::AdapterPool do
|
4
|
-
class DummyAdapter < NinjaModel::Adapters::AbstractAdapter; end
|
5
|
-
before {
|
6
|
-
@spec = NinjaModel::Adapters::AdapterSpecification.new({}, :dummy)
|
7
|
-
NinjaModel::Base.register_adapter(:dummy, DummyAdapter)
|
8
|
-
@pool = NinjaModel::Adapters::AdapterPool.new(@spec)
|
9
|
-
}
|
10
|
-
subject { @pool }
|
11
|
-
its(:spec) { should eql(@spec) }
|
12
|
-
its(:instances) { should be_empty }
|
13
|
-
its(:connected?) { should be_false }
|
14
|
-
its(:current_instance_id) { should eql(Thread.current.object_id) }
|
15
|
-
|
16
|
-
describe 'obtaining an adapter instance' do
|
17
|
-
it 'should store the instance for a given thread' do
|
18
|
-
subject.instance
|
19
|
-
subject.expects(:checkout).never
|
20
|
-
subject.instance
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe 'releasing an adapter instance' do
|
25
|
-
it 'should call checkout when obtaining another instance' do
|
26
|
-
subject.expects(:checkout).twice
|
27
|
-
subject.instance
|
28
|
-
subject.release_instance
|
29
|
-
subject.instance
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe 'with_instance' do
|
34
|
-
it 'should yield an instance' do
|
35
|
-
@inst = nil
|
36
|
-
subject.with_instance do |inst|
|
37
|
-
@inst = inst
|
38
|
-
end
|
39
|
-
@inst.should be_kind_of(DummyAdapter)
|
40
|
-
end
|
41
|
-
it 'should release the instance when complete' do
|
42
|
-
subject.expects(:release_instance).with(subject.send :current_instance_id)
|
43
|
-
subject.with_instance do |inst|
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe 'shutdown!' do
|
49
|
-
it 'should checkin all assigned instances' do
|
50
|
-
@inst = subject.instance
|
51
|
-
subject.expects(:checkin).with(@inst)
|
52
|
-
subject.shutdown!
|
53
|
-
end
|
54
|
-
it 'should call disconnect on all instances' do
|
55
|
-
@inst = subject.instance
|
56
|
-
@inst.expects(:disconnect!)
|
57
|
-
subject.shutdown!
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe 'clear_stale_cached_instances!' do
|
62
|
-
let(:thread) { mock('Thread') }
|
63
|
-
before { Thread.stubs(:list).returns([thread]) }
|
64
|
-
it 'should reap any instances for dead threads' do
|
65
|
-
thread.stubs(:alive?).returns(false)
|
66
|
-
inst = subject.instance
|
67
|
-
subject.instance_variable_set("@assigned_instances".to_sym, {thread.object_id => inst})
|
68
|
-
subject.expects(:checkin).with(inst)
|
69
|
-
subject.send :clear_stale_cached_instances!
|
70
|
-
end
|
71
|
-
it 'should not reap instances for live threads' do
|
72
|
-
thread.stubs(:alive?).returns(true)
|
73
|
-
inst = subject.instance
|
74
|
-
subject.instance_variable_set("@assigned_instances".to_sym, {thread.object_id => inst})
|
75
|
-
subject.expects(:checkin).with(inst).never
|
76
|
-
subject.send :clear_stale_cached_instances!
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe 'checkout' do
|
81
|
-
subject { NinjaModel::Adapters::AdapterPool.new(@spec) }
|
82
|
-
context 'with no current instances' do
|
83
|
-
it 'should checkout a new instance' do
|
84
|
-
subject.expects(:checkout_new_instance).returns('foo')
|
85
|
-
subject.send(:checkout)
|
86
|
-
end
|
87
|
-
it 'should store the instance' do
|
88
|
-
subject.send(:checkout)
|
89
|
-
subject.instances.count.should eql(1)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'with 1 existing instance' do
|
94
|
-
context 'that is already assigned' do
|
95
|
-
it 'should checkout a new instance' do
|
96
|
-
threads = []
|
97
|
-
subject.expects(:new_instance).twice.returns(NinjaModel::Adapters::AdapterManager.registered[subject.spec.name].new(subject.spec.config))
|
98
|
-
2.times do |idx|
|
99
|
-
threads << Thread.new do
|
100
|
-
subject.send(:checkout)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
threads.each { |t| t.join }
|
104
|
-
end
|
105
|
-
end
|
106
|
-
context 'that is not assigned' do
|
107
|
-
it 'should checkout the existing instance' do
|
108
|
-
subject.expects(:checkout_existing_instance).returns('existing')
|
109
|
-
subject.instance
|
110
|
-
subject.release_instance
|
111
|
-
subject.instances.count.should eql(1)
|
112
|
-
subject.send(:checkout)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context 'with the maximum number of instances' do
|
118
|
-
context 'with an available instance' do
|
119
|
-
it 'should successfully check out an instance' do
|
120
|
-
subject.instance
|
121
|
-
threads = []
|
122
|
-
4.times do |idx|
|
123
|
-
threads << Thread.new do
|
124
|
-
subject.instance
|
125
|
-
end
|
126
|
-
end
|
127
|
-
threads.each { |t| t.join }
|
128
|
-
subject.release_instance
|
129
|
-
subject.send(:checkout).should_not be_nil
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
context 'with no available instances' do
|
134
|
-
it 'should raise a ConnectionTimeoutError' do
|
135
|
-
threads = []
|
136
|
-
5.times do |idx|
|
137
|
-
threads << Thread.new do
|
138
|
-
subject.instance
|
139
|
-
end
|
140
|
-
end
|
141
|
-
threads.each { |t| t.join }
|
142
|
-
subject.stubs(:clear_stale_cached_instances!)
|
143
|
-
lambda { subject.instance }.should raise_error(NinjaModel::ConnectionTimeoutError)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'with instances that can be reaped' do
|
148
|
-
it 'should return an existing instance' do
|
149
|
-
threads = []
|
150
|
-
5.times do |idx|
|
151
|
-
threads << Thread.new do
|
152
|
-
subject.instance
|
153
|
-
end
|
154
|
-
end
|
155
|
-
threads.each { |t| t.join }
|
156
|
-
subject.expects(:checkout_existing_instance).returns('foo')
|
157
|
-
subject.instance
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|
163
|
-
# before(:each) do
|
164
|
-
# @spec = mock('AdapterSpecification') do
|
165
|
-
# stubs(:adapter_method).returns(:dummy_adapter)
|
166
|
-
# stubs(:config)
|
167
|
-
# end
|
168
|
-
#
|
169
|
-
# @adapter = mock('AbstractAdapter') do
|
170
|
-
# stubs(:verify!)
|
171
|
-
# end
|
172
|
-
#
|
173
|
-
# @pool = NinjaModel::Adapters::AdapterPool.new(@spec)
|
174
|
-
# @thread = mock('thread') do
|
175
|
-
# stubs('object_id').returns(123)
|
176
|
-
# end
|
177
|
-
# Thread.stubs(:current).returns(@thread)
|
178
|
-
# NinjaModel::Base.stubs(:dummy_adapter).returns(@adapter)
|
179
|
-
# end
|
180
|
-
#
|
181
|
-
# it 'should properly respond to connected?' do
|
182
|
-
# @pool.connected?.should be_false
|
183
|
-
# @pool.instance
|
184
|
-
# @pool.connected?.should be_true
|
185
|
-
# end
|
186
|
-
#
|
187
|
-
# it 'should initialize from an AdapterSpecification' do
|
188
|
-
# spec = mock('AdapterSpecification')
|
189
|
-
# NinjaModel::Adapters::AdapterPool.new(spec).spec.should eql(spec)
|
190
|
-
# end
|
191
|
-
#
|
192
|
-
# it 'should return a valid instance_id' do
|
193
|
-
# (@pool.send :current_instance_id).should eql(@thread.object_id)
|
194
|
-
# end
|
195
|
-
#
|
196
|
-
# describe 'when creating an instance' do
|
197
|
-
# it 'should create a valid instance' do
|
198
|
-
# (@pool.send :new_instance).should eql(@adapter)
|
199
|
-
# end
|
200
|
-
#
|
201
|
-
# it 'should store the instance' do
|
202
|
-
# @pool.stubs(:new_instance).returns(@adapter)
|
203
|
-
# @pool.instance
|
204
|
-
# @pool.instances.should include(@adapter)
|
205
|
-
# end
|
206
|
-
#
|
207
|
-
# it 'should assign the instance to the current_thread' do
|
208
|
-
# @pool.stubs(:new_instance).returns(@adapter)
|
209
|
-
# @pool.instance
|
210
|
-
# @pool.stubs(:checkout).returns("new_instance")
|
211
|
-
# @pool.instance.should_not eql("new_instance")
|
212
|
-
# @pool.instance.should eql(@adapter)
|
213
|
-
# end
|
214
|
-
#
|
215
|
-
# it 'should reuse an unallocated instance' do
|
216
|
-
# @pool.stubs(:current_instance_id).returns(123)
|
217
|
-
# inst = @pool.instance
|
218
|
-
# @pool.release_instance(123)
|
219
|
-
# @pool.instance.should eql(inst)
|
220
|
-
# end
|
221
|
-
# end
|
222
|
-
#
|
223
|
-
# it 'should properly allocate/deallocate instances' do
|
224
|
-
# @pool.stubs(:current_instance_id).returns(123)
|
225
|
-
# @pool.expects(:checkout).returns(@adapter)
|
226
|
-
# @pool.expects(:checkin)
|
227
|
-
# @pool.with_instance do |instance|
|
228
|
-
# end
|
229
|
-
# end
|
230
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe NinjaModel::Adapters do
|
4
|
-
class DummyAdapter < NinjaModel::Adapters::AbstractAdapter; end
|
5
|
-
class SmarterAdapter < NinjaModel::Adapters::AbstractAdapter; end
|
6
|
-
before {
|
7
|
-
NinjaModel::Base.register_adapter(:dummy, DummyAdapter)
|
8
|
-
NinjaModel::Base.register_adapter(:smarter, SmarterAdapter)
|
9
|
-
}
|
10
|
-
subject { Class.new(NinjaModel::Base) }
|
11
|
-
it { should respond_to(:register_adapter) }
|
12
|
-
it { should respond_to(:set_adapter) }
|
13
|
-
|
14
|
-
describe 'adapter' do
|
15
|
-
before { @klass = Class.new(NinjaModel::Base) }
|
16
|
-
subject { @klass.new }
|
17
|
-
it 'should call retrieve_adapter' do
|
18
|
-
@klass.expects(:retrieve_adapter)
|
19
|
-
subject.adapter
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe 'register_adapter' do
|
24
|
-
it 'should register with the adapter manager' do
|
25
|
-
subject.adapter_manager.class.expects(:register_adapter_class).with(:dummy, DummyAdapter)
|
26
|
-
subject.register_adapter(:dummy, DummyAdapter)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe 'set_adapter' do
|
31
|
-
before {
|
32
|
-
@configuration = mock('Configuration') do
|
33
|
-
stubs(:specs).returns({'development' => {:adapter => :dummy}})
|
34
|
-
end
|
35
|
-
NinjaModel.stubs(:configuration).returns(@configuration)
|
36
|
-
@klass = Class.new(NinjaModel::Base)
|
37
|
-
}
|
38
|
-
subject { @klass }
|
39
|
-
context 'when nil is passed' do
|
40
|
-
it 'should return a DummyAdapter if Rails is available' do
|
41
|
-
@rails = Object.const_set('Rails', Class.new(Object))
|
42
|
-
@rails.stubs(:env).returns('development')
|
43
|
-
subject.set_adapter.spec.name.should eql(:dummy)
|
44
|
-
Object.send(:remove_const, :Rails)
|
45
|
-
end
|
46
|
-
it 'should raise AdapterNotSpecified is Rails is not available' do
|
47
|
-
lambda { subject.set_adapter }.should raise_error(NinjaModel::Adapters::AdapterNotSpecified)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
it 'should return a DummyAdapter pool when "development" is passed' do
|
51
|
-
subject.set_adapter('development').spec.name.should eql(:dummy)
|
52
|
-
end
|
53
|
-
it 'should return a DummyAdapter pool when a dummy specification is passed' do
|
54
|
-
subject.set_adapter(:adapter => :dummy).spec.name.should eql(:dummy)
|
55
|
-
end
|
56
|
-
it 'should return a SmarterAdapter pool when a smarter specification is passed' do
|
57
|
-
subject.set_adapter(:adapter => :smarter).spec.name.should eql(:smarter)
|
58
|
-
end
|
59
|
-
it 'should raise AdapterNotSpecified if the configuration doesn\'t specify an adapter' do
|
60
|
-
lambda { subject.set_adapter({}) }.should raise_error(NinjaModel::Adapters::AdapterNotSpecified)
|
61
|
-
end
|
62
|
-
it 'should raise InvalidAdapter for an invalid adapter name' do
|
63
|
-
lambda { subject.set_adapter(:adapter => :bogus) }.should raise_error(NinjaModel::Adapters::InvalidAdapter)
|
64
|
-
end
|
65
|
-
it 'should raise InvalidSpecification for an invalid Rails.env' do
|
66
|
-
lambda { subject.set_adapter('foobar') }.should raise_error(NinjaModel::Adapters::InvalidSpecification)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe 'retrieve_adapter' do
|
71
|
-
before { @klass = Class.new(NinjaModel::Base) }
|
72
|
-
it 'should call retrieve_adapter on the manager' do
|
73
|
-
@klass.adapter_manager.expects(:retrieve_adapter).with(@klass)
|
74
|
-
@klass.retrieve_adapter
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe 'shutdown_adapter' do
|
79
|
-
before { @klass = Class.new(NinjaModel::Base) }
|
80
|
-
it 'should call remove_adapter on the manager' do
|
81
|
-
@klass.adapter_manager.expects(:remove_adapter).with(@klass)
|
82
|
-
@klass.shutdown_adapter
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|