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.
Files changed (72) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +1 -0
  3. data/Rakefile +6 -0
  4. data/lib/ninja_model.rb +23 -7
  5. data/lib/ninja_model/adapters.rb +25 -20
  6. data/lib/ninja_model/adapters/adapter_manager.rb +2 -0
  7. data/lib/ninja_model/adapters/adapter_pool.rb +2 -0
  8. data/lib/ninja_model/associations.rb +63 -101
  9. data/lib/ninja_model/associations/association.rb +146 -0
  10. data/lib/ninja_model/associations/association_scope.rb +39 -0
  11. data/lib/ninja_model/associations/belongs_to_association.rb +33 -21
  12. data/lib/ninja_model/associations/builder/association.rb +57 -0
  13. data/lib/ninja_model/associations/builder/belongs_to.rb +33 -0
  14. data/lib/ninja_model/associations/builder/collection_association.rb +60 -0
  15. data/lib/ninja_model/associations/builder/has_many.rb +11 -0
  16. data/lib/ninja_model/associations/builder/has_one.rb +20 -0
  17. data/lib/ninja_model/associations/builder/singular_association.rb +49 -0
  18. data/lib/ninja_model/associations/collection_association.rb +103 -0
  19. data/lib/ninja_model/associations/collection_proxy.rb +45 -0
  20. data/lib/ninja_model/associations/has_many_association.rb +19 -43
  21. data/lib/ninja_model/associations/has_one_association.rb +52 -6
  22. data/lib/ninja_model/associations/singular_association.rb +61 -0
  23. data/lib/ninja_model/attribute.rb +5 -2
  24. data/lib/ninja_model/attribute_methods.rb +35 -40
  25. data/lib/ninja_model/base.rb +31 -39
  26. data/lib/ninja_model/identity.rb +8 -6
  27. data/lib/ninja_model/rails_ext/active_record.rb +69 -225
  28. data/lib/ninja_model/railtie.rb +0 -9
  29. data/lib/ninja_model/reflection.rb +103 -20
  30. data/lib/ninja_model/relation.rb +2 -2
  31. data/lib/ninja_model/relation/query_methods.rb +16 -0
  32. data/lib/ninja_model/version.rb +1 -1
  33. data/ninja-model.gemspec +2 -1
  34. data/spec/db/schema.rb +15 -0
  35. data/spec/{ninja_model → lib/ninja_model}/adapters/abstract_adapter_spec.rb +0 -0
  36. data/spec/lib/ninja_model/adapters/adapter_manager_spec.rb +72 -0
  37. data/spec/lib/ninja_model/adapters/adapter_pool_spec.rb +230 -0
  38. data/spec/lib/ninja_model/adapters_spec.rb +120 -0
  39. data/spec/lib/ninja_model/associations/belongs_to_association_spec.rb +76 -0
  40. data/spec/lib/ninja_model/associations/has_many_association_spec.rb +118 -0
  41. data/spec/lib/ninja_model/associations/has_one_association_spec.rb +80 -0
  42. data/spec/{ninja_model → lib/ninja_model}/attribute_methods_spec.rb +2 -2
  43. data/spec/{ninja_model → lib/ninja_model}/attribute_spec.rb +4 -0
  44. data/spec/{ninja_model → lib/ninja_model}/base_spec.rb +0 -0
  45. data/spec/{ninja_model → lib/ninja_model}/identity_spec.rb +0 -0
  46. data/spec/{ninja_model → lib/ninja_model}/persistence_spec.rb +0 -0
  47. data/spec/{ninja_model → lib/ninja_model}/predicate_spec.rb +0 -0
  48. data/spec/{ninja_model → lib/ninja_model}/query_methods_spec.rb +0 -0
  49. data/spec/{ninja_model → lib/ninja_model}/reflection_spec.rb +7 -9
  50. data/spec/{ninja_model → lib/ninja_model}/relation_spec.rb +0 -0
  51. data/spec/{ninja_model → lib/ninja_model}/symbol_spec.rb +0 -0
  52. data/spec/{ninja_model → lib/ninja_model}/validation_spec.rb +0 -0
  53. data/spec/{ninja_model_spec.rb → lib/ninja_model_spec.rb} +0 -0
  54. data/spec/models/bio.rb +8 -0
  55. data/spec/models/body.rb +7 -0
  56. data/spec/models/category.rb +7 -0
  57. data/spec/models/email_address.rb +3 -0
  58. data/spec/models/post.rb +13 -0
  59. data/spec/models/tag.rb +3 -0
  60. data/spec/models/user.rb +4 -0
  61. data/spec/spec_helper.rb +38 -5
  62. data/spec/support/dummy_adapter/adapter.rb +48 -0
  63. data/spec/support/factories/bio.rb +11 -0
  64. data/spec/support/factories/body.rb +12 -0
  65. data/spec/support/factories/email_address.rb +5 -0
  66. data/spec/support/factories/post.rb +12 -0
  67. data/spec/support/factories/tag.rb +5 -0
  68. data/spec/support/factories/user.rb +5 -0
  69. metadata +121 -63
  70. data/spec/ninja_model/adapters/adapter_manager_spec.rb +0 -69
  71. data/spec/ninja_model/adapters/adapter_pool_spec.rb +0 -230
  72. 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