ninja-model 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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