simply_stored 0.3.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/CHANGELOG.md +38 -0
  2. data/README.md +45 -24
  3. data/lib/simply_stored/couch/association_property.rb +27 -0
  4. data/lib/simply_stored/couch/belongs_to.rb +5 -7
  5. data/lib/simply_stored/couch/finders.rb +5 -1
  6. data/lib/simply_stored/couch/has_and_belongs_to_many.rb +202 -0
  7. data/lib/simply_stored/couch/has_many.rb +6 -51
  8. data/lib/simply_stored/couch/has_one.rb +4 -29
  9. data/lib/simply_stored/couch/properties.rb +11 -0
  10. data/lib/simply_stored/couch.rb +38 -2
  11. data/lib/simply_stored/instance_methods.rb +68 -29
  12. data/lib/simply_stored.rb +3 -1
  13. data/test/{couchdb/couch_active_model_compatibility_test.rb → active_model_compatibility_test.rb} +2 -2
  14. data/test/{couchdb/couch_belongs_to_test.rb → belongs_to_test.rb} +13 -3
  15. data/test/{couchdb/couch_conflict_handling_test.rb → conflict_handling_test.rb} +3 -3
  16. data/test/{couchdb/couch_finder_test.rb → finder_test.rb} +8 -3
  17. data/test/fixtures/couch.rb +55 -0
  18. data/test/has_and_belongs_to_many_test.rb +639 -0
  19. data/test/{couchdb/couch_has_many_test.rb → has_many_test.rb} +13 -3
  20. data/test/{couchdb/couch_has_one_test.rb → has_one_test.rb} +13 -3
  21. data/test/{couchdb/couch_instance_lifecycle_test.rb → instance_lifecycle_test.rb} +3 -3
  22. data/test/{couchdb/couch_mass_assignment_protection_test.rb → mass_assignment_protection_test.rb} +3 -3
  23. data/test/{couchdb/couch_s3_test.rb → s3_test.rb} +3 -3
  24. data/test/{couchdb/couch_soft_deletable_test.rb → soft_deletable_test.rb} +3 -3
  25. data/test/test_helper.rb +1 -5
  26. data/test/{couchdb/couch_validations_test.rb → validations_test.rb} +3 -3
  27. data/test/{couchdb/custom_views_test.rb → views_test.rb} +3 -3
  28. metadata +36 -234
  29. data/lib/simply_stored/simpledb/associations.rb +0 -215
  30. data/lib/simply_stored/simpledb/attributes.rb +0 -173
  31. data/lib/simply_stored/simpledb/storag.rb +0 -85
  32. data/lib/simply_stored/simpledb/validations.rb +0 -88
  33. data/lib/simply_stored/simpledb.rb +0 -216
  34. data/test/fixtures/simpledb/item.rb +0 -11
  35. data/test/fixtures/simpledb/item_daddy.rb +0 -8
  36. data/test/fixtures/simpledb/log_item.rb +0 -3
  37. data/test/fixtures/simpledb/namespace_bar.rb +0 -5
  38. data/test/fixtures/simpledb/namespace_foo.rb +0 -7
  39. data/test/fixtures/simpledb/protected_item.rb +0 -3
  40. data/test/simply_stored_simpledb_test.rb +0 -1376
  41. data/test/vendor/dhaka-2.2.1/lib/dhaka/dot/dot.rb +0 -29
  42. data/test/vendor/dhaka-2.2.1/lib/dhaka/evaluator/evaluator.rb +0 -133
  43. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/closure_hash.rb +0 -15
  44. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar.rb +0 -240
  45. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar_symbol.rb +0 -27
  46. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/precedence.rb +0 -19
  47. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/production.rb +0 -36
  48. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/accept_actions.rb +0 -36
  49. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/alphabet.rb +0 -21
  50. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/compiled_lexer.rb +0 -46
  51. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/dfa.rb +0 -121
  52. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexeme.rb +0 -32
  53. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer.rb +0 -70
  54. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer_run.rb +0 -78
  55. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_grammar.rb +0 -392
  56. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_parser.rb +0 -2010
  57. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_tokenizer.rb +0 -14
  58. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/specification.rb +0 -96
  59. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state.rb +0 -68
  60. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state_machine.rb +0 -37
  61. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/action.rb +0 -55
  62. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/channel.rb +0 -58
  63. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/compiled_parser.rb +0 -51
  64. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/conflict.rb +0 -54
  65. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/item.rb +0 -42
  66. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_result.rb +0 -50
  67. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_tree.rb +0 -66
  68. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser.rb +0 -165
  69. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_methods.rb +0 -11
  70. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_run.rb +0 -39
  71. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_state.rb +0 -74
  72. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/token.rb +0 -22
  73. data/test/vendor/dhaka-2.2.1/lib/dhaka/runtime.rb +0 -51
  74. data/test/vendor/dhaka-2.2.1/lib/dhaka/tokenizer/tokenizer.rb +0 -190
  75. data/test/vendor/dhaka-2.2.1/lib/dhaka.rb +0 -62
  76. data/test/vendor/dhaka-2.2.1/test/all_tests.rb +0 -5
  77. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator.rb +0 -64
  78. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator_test.rb +0 -43
  79. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar.rb +0 -41
  80. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar_test.rb +0 -9
  81. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_test_methods.rb +0 -9
  82. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer.rb +0 -39
  83. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer_test.rb +0 -38
  84. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_evaluator.rb +0 -43
  85. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar.rb +0 -24
  86. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar_test.rb +0 -30
  87. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_lexer_specification.rb +0 -23
  88. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_parser_test.rb +0 -33
  89. data/test/vendor/dhaka-2.2.1/test/brackets/bracket_grammar.rb +0 -23
  90. data/test/vendor/dhaka-2.2.1/test/brackets/bracket_tokenizer.rb +0 -22
  91. data/test/vendor/dhaka-2.2.1/test/brackets/brackets_test.rb +0 -28
  92. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver.rb +0 -46
  93. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver_test.rb +0 -276
  94. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator.rb +0 -284
  95. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator_test.rb +0 -38
  96. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_grammar.rb +0 -104
  97. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer.rb +0 -109
  98. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_specification.rb +0 -37
  99. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_test.rb +0 -58
  100. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser.rb +0 -879
  101. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser_test.rb +0 -55
  102. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_test.rb +0 -170
  103. data/test/vendor/dhaka-2.2.1/test/core/another_lalr_but_not_slr_grammar.rb +0 -20
  104. data/test/vendor/dhaka-2.2.1/test/core/compiled_parser_test.rb +0 -44
  105. data/test/vendor/dhaka-2.2.1/test/core/dfa_test.rb +0 -170
  106. data/test/vendor/dhaka-2.2.1/test/core/evaluator_test.rb +0 -22
  107. data/test/vendor/dhaka-2.2.1/test/core/grammar_test.rb +0 -83
  108. data/test/vendor/dhaka-2.2.1/test/core/lalr_but_not_slr_grammar.rb +0 -19
  109. data/test/vendor/dhaka-2.2.1/test/core/lexer_test.rb +0 -139
  110. data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar.rb +0 -7
  111. data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar_test.rb +0 -8
  112. data/test/vendor/dhaka-2.2.1/test/core/nullable_grammar.rb +0 -21
  113. data/test/vendor/dhaka-2.2.1/test/core/parse_result_test.rb +0 -44
  114. data/test/vendor/dhaka-2.2.1/test/core/parser_state_test.rb +0 -24
  115. data/test/vendor/dhaka-2.2.1/test/core/parser_test.rb +0 -131
  116. data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar.rb +0 -17
  117. data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar_test.rb +0 -9
  118. data/test/vendor/dhaka-2.2.1/test/core/rr_conflict_grammar.rb +0 -21
  119. data/test/vendor/dhaka-2.2.1/test/core/simple_grammar.rb +0 -22
  120. data/test/vendor/dhaka-2.2.1/test/core/sr_conflict_grammar.rb +0 -16
  121. data/test/vendor/dhaka-2.2.1/test/dhaka_test_helper.rb +0 -17
  122. data/test/vendor/dhaka-2.2.1/test/fake_logger.rb +0 -17
  123. data/test/vendor/simplerdb-0.2/lib/simplerdb/client_exception.rb +0 -10
  124. data/test/vendor/simplerdb-0.2/lib/simplerdb/db.rb +0 -146
  125. data/test/vendor/simplerdb-0.2/lib/simplerdb/query_language.rb +0 -266
  126. data/test/vendor/simplerdb-0.2/lib/simplerdb/server.rb +0 -33
  127. data/test/vendor/simplerdb-0.2/lib/simplerdb/servlet.rb +0 -191
  128. data/test/vendor/simplerdb-0.2/lib/simplerdb.rb +0 -3
  129. data/test/vendor/simplerdb-0.2/test/functional_test.rb +0 -81
  130. data/test/vendor/simplerdb-0.2/test/query_evaluator_test.rb +0 -73
  131. data/test/vendor/simplerdb-0.2/test/query_parser_test.rb +0 -64
  132. data/test/vendor/simplerdb-0.2/test/simplerdb_test.rb +0 -80
@@ -0,0 +1,639 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/couch')
3
+
4
+ class HasAndBelongsToManyTest < Test::Unit::TestCase
5
+ context "has_and_belongs_to_many" do
6
+ setup do
7
+ CouchPotato::Config.database_name = 'simply_stored_test'
8
+ recreate_db
9
+ end
10
+
11
+ context "with has_and_belongs_to_many" do
12
+ should "create a fetch method for the associated objects" do
13
+ server = Server.new
14
+ assert server.respond_to?(:networks)
15
+
16
+ network = Network.new
17
+ assert network.respond_to?(:servers)
18
+ end
19
+
20
+ should "raise an error if another property with the same name already exists" do
21
+ assert_raise(RuntimeError) do
22
+ class ::DoubleHasAdnBelongsToManyServer
23
+ include SimplyStored::Couch
24
+ property :other_users
25
+ has_and_belongs_to_many :other_users
26
+ end
27
+ end
28
+ end
29
+
30
+ should "fetch the associated objects" do
31
+ network = Network.create(:klass => "A")
32
+ 3.times {
33
+ server = Server.new
34
+ server.network_ids = [network.id]
35
+ server.save!
36
+ }
37
+ assert_equal 3, network.servers.size
38
+ end
39
+
40
+ should "fetch the associated objects from the other side of the relation" do
41
+ network = Network.create(:klass => "A")
42
+ 3.times {
43
+ server = Server.new
44
+ server.network_ids = [network.id]
45
+ server.save!
46
+ }
47
+ assert_equal 1, Server.first.networks.size
48
+ end
49
+
50
+ should "set the parent object on the clients cache" do
51
+ Network.expects(:find).never
52
+ network = Network.create(:klass => "A")
53
+ 3.times {
54
+ server = Server.new
55
+ server.add_network(network)
56
+ }
57
+ assert_equal network, network.servers.first.networks.first
58
+ end
59
+
60
+ should "set the parent object on the clients cache from the other side of the relation" do
61
+ Server.expects(:find).never
62
+ network = Network.create(:klass => "A")
63
+ 3.times {
64
+ server = Server.new
65
+ network.add_server(server)
66
+ }
67
+ assert_equal network, network.servers.first.networks.first
68
+ end
69
+
70
+ should "work relations from both sides" do
71
+ network_a = Network.create(:klass => "A")
72
+ network_b = Network.create(:klass => "B")
73
+ 3.times {
74
+ server = Server.new
75
+ server.add_network(network_a)
76
+ server.add_network(network_b)
77
+ }
78
+ assert_equal 3, network_a.servers.size
79
+ network_a.servers.each do |server|
80
+ assert_equal 2, server.networks.size
81
+ end
82
+ assert_equal 3, network_b.servers.size
83
+ network_b.servers.each do |server|
84
+ assert_equal 2, server.networks.size
85
+ end
86
+ end
87
+
88
+ should "work relations from both sides - regardless from where the add was called" do
89
+ network_a = Network.create(:klass => "A")
90
+ network_b = Network.create(:klass => "B")
91
+ 3.times {
92
+ server = Server.new
93
+ network_a.add_server(server)
94
+ network_b.add_server(server)
95
+ }
96
+ assert_equal 3, network_a.servers.size
97
+ network_a.servers.each do |server|
98
+ assert_equal 2, server.networks.size, server.network_ids.inspect
99
+ end
100
+ assert_equal 3, network_b.servers.size
101
+ network_b.servers.each do |server|
102
+ assert_equal 2, server.networks.size
103
+ end
104
+ end
105
+
106
+ context "limit" do
107
+
108
+ should "be able to limit the result set" do
109
+ network = Network.create(:klass => "A")
110
+ 3.times {
111
+ server = Server.new
112
+ server.add_network(network)
113
+ }
114
+ assert_equal 2, network.servers(:limit => 2).size
115
+ end
116
+
117
+ should "use the given options in the cache-key" do
118
+ network = Network.create(:klass => "A")
119
+ 3.times {
120
+ server = Server.new
121
+ server.add_network(network)
122
+ }
123
+ assert_equal 2, network.servers(:limit => 2).size
124
+ assert_equal 3, network.servers(:limit => 3).size
125
+ end
126
+
127
+ should "be able to limit the result set - for both directions" do
128
+ network_a = Network.create(:klass => "A")
129
+ network_b = Network.create(:klass => "B")
130
+ 3.times {
131
+ server = Server.new
132
+ server.add_network(network_a)
133
+ server.add_network(network_b)
134
+ }
135
+ assert_equal 2, network_a.servers(:limit => 2).size
136
+ assert_equal 3, network_a.servers(:limit => 3).size
137
+
138
+ assert_equal 2, network_a.servers.first.networks(:limit => 2).size
139
+ assert_equal 1, network_a.servers.first.networks(:limit => 1).size
140
+ end
141
+ end
142
+
143
+ context "order" do
144
+ setup do
145
+ @network = Network.create(:klass => "A")
146
+ @network.created_at = Time.local(2000)
147
+ @network.save!
148
+ @network_b = Network.create(:klass => "B")
149
+ @network_b.created_at = Time.local(2002)
150
+ @network_b.save!
151
+ 3.times do |i|
152
+ server = Server.new
153
+ server.add_network(@network)
154
+ server.add_network(@network_b)
155
+ server.created_at = Time.local(2000 + i)
156
+ server.save!
157
+ end
158
+ end
159
+
160
+ should "support different order" do
161
+ assert_nothing_raised do
162
+ @network.servers(:order => :asc)
163
+ end
164
+
165
+ assert_nothing_raised do
166
+ @network.servers(:order => :desc)
167
+ end
168
+ end
169
+
170
+ should "reverse the order if :desc" do
171
+ assert_equal @network.servers(:order => :asc).map(&:id).reverse, @network.servers(:order => :desc).map(&:id)
172
+ server = @network.servers.first
173
+ assert_equal server.networks(:order => :asc).map(&:id).reverse, server.networks(:order => :desc).map(&:id)
174
+ end
175
+
176
+ should "work with the limit option" do
177
+ server = Server.new
178
+ server.add_network(@network)
179
+ server.add_network(@network_b)
180
+ assert_not_equal @network.servers(:order => :asc, :limit => 3).map(&:id).reverse, @network.servers(:order => :desc, :limit => 3).map(&:id)
181
+ assert_not_equal server.networks(:order => :asc, :limit => 1).map(&:id).reverse, server.networks(:order => :desc, :limit => 1).map(&:id)
182
+ end
183
+ end
184
+
185
+ should "verify the given options for the accessor method" do
186
+ network = Network.create(:klass => "A")
187
+ assert_raise(ArgumentError) do
188
+ network.servers(:foo => :bar)
189
+ end
190
+ end
191
+
192
+ should "verify the given options for the association defintion" do
193
+ assert_raise(ArgumentError) do
194
+ Network.instance_eval do
195
+ has_and_belongs_to_many :foo, :bar => :do
196
+ end
197
+ end
198
+ end
199
+
200
+ should "only fetch objects of the correct type" do
201
+ network = Network.create(:klass => "A")
202
+ server = Server.new
203
+ server.network_ids = [network.id]
204
+ server.save!
205
+
206
+ comment = Comment.new
207
+ comment.network = network
208
+ comment.save!
209
+
210
+ assert_equal 1, network.servers.size
211
+ end
212
+
213
+ should "getter should user cache" do
214
+ network = Network.create(:klass => "A")
215
+ server = Server.new
216
+ server.network_ids = [network.id]
217
+ server.save!
218
+ network.servers
219
+ assert_equal [server], network.instance_variable_get("@servers")[:all]
220
+ end
221
+
222
+ should "add methods to handle associated objects" do
223
+ network = Network.create(:klass => "A")
224
+ assert network.respond_to?(:add_server)
225
+ assert network.respond_to?(:remove_server)
226
+ assert network.respond_to?(:remove_all_servers)
227
+ end
228
+
229
+ should "add methods to handle associated objects - for the other side too" do
230
+ server = Server.create
231
+ assert server.respond_to?(:add_network)
232
+ assert server.respond_to?(:remove_network)
233
+ assert server.respond_to?(:remove_all_networks)
234
+ end
235
+
236
+ should 'ignore the cache when requesting explicit reload' do
237
+ network = Network.create(:klass => "A")
238
+ assert_equal [], network.servers
239
+ server = Server.new
240
+ server.network_ids = [network.id]
241
+ server.save!
242
+ assert_equal [server], network.servers(:force_reload => true)
243
+ end
244
+
245
+ should "use the correct view when handling inheritance" do
246
+ network = Network.create
247
+ subnet = Subnet.create
248
+ server = Server.new
249
+ server.network_ids = [network.id]
250
+ server.save!
251
+ assert_equal 1, network.servers.size
252
+ server.update_attributes(:network_ids => nil, :subnet_ids => [subnet.id])
253
+ assert_equal 1, subnet.servers.size
254
+ end
255
+
256
+ context "when adding items" do
257
+ should "add the item to the internal cache" do
258
+ network = Network.new(:klass => "C")
259
+ server = Server.new
260
+ assert_equal [], network.servers
261
+ network.add_server(server)
262
+ assert_equal [server], network.servers
263
+ assert_equal [server], network.instance_variable_get("@servers")[:all]
264
+ end
265
+
266
+ should "raise an error when the added item is not an object of the expected class" do
267
+ network = Network.new
268
+ assert_raise(ArgumentError, 'excepted Server got String') do
269
+ network.add_server('foo')
270
+ end
271
+ end
272
+
273
+ should "save the added item" do
274
+ server = Server.new
275
+ network = Network.create(:klass => "A")
276
+ network.add_server(server)
277
+ assert !server.new_record?
278
+ end
279
+
280
+ should "save the added item - from both directions" do
281
+ server = Server.new
282
+ network = Network.create(:klass => "A")
283
+ server.add_network(network)
284
+ assert !server.new_record?
285
+ end
286
+
287
+ should 'set the forein key on the added object' do
288
+ server = Server.new
289
+ network = Network.create(:klass => "A")
290
+ network.add_server(server)
291
+ assert_equal [network.id], server.network_ids
292
+ end
293
+
294
+ should 'set the forein key on the added object - from both directions' do
295
+ server = Server.new
296
+ network = Network.create(:klass => "A")
297
+ server.add_network(network)
298
+ assert_equal [network.id], server.network_ids
299
+ end
300
+
301
+ should "adding multiple times doesn't hurt" do
302
+ server = Server.new
303
+ network = Network.create(:klass => "A")
304
+ network.add_server(server)
305
+ network.add_server(server)
306
+ server.add_network(network)
307
+ assert_equal [network.id], server.network_ids
308
+ assert_equal [network.id], Server.find(server.id).network_ids
309
+ end
310
+ end
311
+
312
+ context "when removing items" do
313
+ should "should unset the foreign key" do
314
+ server = Server.new
315
+ network = Network.create(:klass => "A")
316
+ network.add_server(server)
317
+
318
+ network.remove_server(server)
319
+ assert_equal [], server.network_ids
320
+ end
321
+
322
+ should "should unset the foreign key - from both directions" do
323
+ server = Server.new
324
+ network = Network.create(:klass => "A")
325
+ network.add_server(server)
326
+
327
+ server.remove_network(network)
328
+ assert_equal [], server.network_ids
329
+ end
330
+
331
+ should "remove the item from the cache" do
332
+ server = Server.new
333
+ network = Network.create(:klass => "A")
334
+ network.add_server(server)
335
+ assert network.servers.include?(server)
336
+ network.remove_server(server)
337
+ assert !network.servers.any?{|s| server.id == s.id}
338
+ assert_equal [], network.instance_variable_get("@servers")[:all]
339
+ end
340
+
341
+ should "remove the item from the cache - from both directions" do
342
+ server = Server.new
343
+ network = Network.create(:klass => "A")
344
+ network.add_server(server)
345
+ assert server.networks.include?(network)
346
+ server.remove_network(network)
347
+ assert !server.networks.any?{|n| network.id == n.id}
348
+ assert_equal [], server.instance_variable_get("@networks")[:all]
349
+ end
350
+
351
+ should "save the removed item with the nullified foreign key" do
352
+ server = Server.new
353
+ network = Network.create(:klass => "A")
354
+ network.add_server(server)
355
+
356
+ network.remove_server(server)
357
+ server = Server.find(server.id)
358
+ assert_equal [], server.network_ids
359
+ end
360
+
361
+ should "save the removed item with the nullified foreign key - from both directions" do
362
+ server = Server.new
363
+ network = Network.create(:klass => "A")
364
+ network.add_server(server)
365
+
366
+ server.remove_network(network)
367
+ server = Server.find(server.id)
368
+ assert_equal [], server.network_ids
369
+ end
370
+
371
+ should 'raise an error when another object is the owner of the object to be removed' do
372
+ server = Server.new
373
+ network = Network.create(:klass => "A")
374
+ network.add_server(server)
375
+
376
+ other_server = Server.create
377
+ assert_raise(ArgumentError) do
378
+ network.remove_server(other_server)
379
+ end
380
+ end
381
+
382
+ should 'raise an error when another object is the owner of the object to be removed - from both directions' do
383
+ server = Server.new
384
+ network = Network.create(:klass => "A")
385
+ network.add_server(server)
386
+
387
+ other_network = Network.create
388
+ assert_raise(ArgumentError) do
389
+ server.remove_network(other_network)
390
+ end
391
+ end
392
+
393
+ should 'raise an error when the object is the wrong type' do
394
+ assert_raise(ArgumentError, 'excepted Server got String') do
395
+ Network.new.remove_server('foo')
396
+ end
397
+ assert_raise(ArgumentError, 'excepted Network got String') do
398
+ Server.new.remove_network('foo')
399
+ end
400
+ end
401
+ end
402
+
403
+ context "when removing all items" do
404
+ should 'nullify the foreign keys on all referenced items' do
405
+ server_1 = Server.new
406
+ server_2 = Server.new
407
+ network = Network.create(:klass => "A")
408
+ network.add_server(server_1)
409
+ network.add_server(server_2)
410
+ network.remove_all_servers
411
+ server_1 = Server.find(server_1.id)
412
+ server_2 = Server.find(server_2.id)
413
+ assert_equal [], server_1.network_ids
414
+ assert_equal [], server_2.network_ids
415
+ end
416
+
417
+ should 'nullify the foreign keys on all referenced items - from both directions' do
418
+ server_1 = Server.new
419
+ server_2 = Server.new
420
+ network = Network.create(:klass => "A")
421
+ network.add_server(server_1)
422
+ network.add_server(server_2)
423
+ server_1.remove_all_networks
424
+ server_1 = Server.find(server_1.id)
425
+ server_2 = Server.find(server_2.id)
426
+ assert_equal [], server_1.network_ids
427
+ assert_equal [network.id], server_2.network_ids
428
+ end
429
+
430
+ should 'empty the cache' do
431
+ server_1 = Server.new
432
+ server_2 = Server.new
433
+ network = Network.create(:klass => "A")
434
+ network.add_server(server_1)
435
+ network.add_server(server_2)
436
+ network.remove_all_servers
437
+ assert_equal [], network.servers
438
+ assert_equal [], network.instance_variable_get("@servers")[:all]
439
+ end
440
+
441
+ should 'empty the cache - from both directions' do
442
+ server_1 = Server.new
443
+ server_2 = Server.new
444
+ network = Network.create(:klass => "A")
445
+ network.add_server(server_1)
446
+ network.add_server(server_2)
447
+ server_1.remove_all_networks
448
+ assert_equal [], server_1.networks
449
+ assert_equal [], server_1.instance_variable_get("@networks")[:all]
450
+ end
451
+
452
+ context "when counting" do
453
+ setup do
454
+ @network = Network.create(:klass => "C")
455
+ @server = Server.create
456
+ end
457
+
458
+ should "define a count method" do
459
+ assert @network.respond_to?(:server_count)
460
+ assert @server.respond_to?(:network_count)
461
+ end
462
+
463
+ should "cache the result" do
464
+ assert_equal 0, @network.server_count
465
+ Server.create(:network_ids => [@network.id])
466
+ assert_equal 0, @network.server_count
467
+ assert_equal 0, @network.instance_variable_get("@server_count")
468
+ @network.instance_variable_set("@server_count", nil)
469
+ assert_equal 1, @network.server_count
470
+ end
471
+
472
+ should "cache the result - from both directions" do
473
+ assert_equal 0, @server.network_count
474
+ @server.network_ids = [@network.id]
475
+ @server.save!
476
+ assert_equal 0, @server.network_count
477
+ assert_equal 0, @server.instance_variable_get("@network_count")
478
+ @server.instance_variable_set("@network_count", nil)
479
+ assert_equal 1, @server.network_count
480
+ end
481
+
482
+ should "force reload even if cached" do
483
+ assert_equal 0, @network.server_count
484
+ Server.create(:network_ids => [@network.id])
485
+ assert_equal 0, @network.server_count
486
+ assert_equal 1, @network.server_count(:force_reload => true)
487
+ end
488
+
489
+ should "force reload even if cached - from both directions" do
490
+ assert_equal 0, @server.network_count
491
+ @server.network_ids = [@network.id]
492
+ @server.save!
493
+ assert_equal 0, @server.network_count
494
+ assert_equal 1, @server.network_count(:force_reload => true)
495
+ end
496
+
497
+ should "count the number of belongs_to objects" do
498
+ assert_equal 0, @network.server_count(:force_reload => true)
499
+ Server.create(:network_ids => [@network.id])
500
+ assert_equal 1, @network.server_count(:force_reload => true)
501
+ Server.create(:network_ids => [@network.id])
502
+ assert_equal 2, @network.server_count(:force_reload => true)
503
+ Server.create(:network_ids => [@network.id])
504
+ assert_equal 3, @network.server_count(:force_reload => true)
505
+ end
506
+
507
+ should "count the number of belongs_to objects - from both directions" do
508
+ assert_equal 0, @server.network_count(:force_reload => true)
509
+ @server.network_ids = [@network.id]
510
+ @server.save!
511
+ assert_equal 1, @server.network_count(:force_reload => true)
512
+ @server.network_ids = [@network.id, Network.create.id]
513
+ @server.save!
514
+ assert_equal 2, @server.network_count(:force_reload => true)
515
+ end
516
+
517
+ should "not count non-releated objects" do
518
+ Server.all.each{|s| s.delete}
519
+ network_1 = Network.create(:klass => "A")
520
+ network_2 = Network.create(:klass => "B")
521
+ server_1 = Server.create
522
+ server_2 = Server.create(:network_ids => [network_1.id])
523
+ server_3 = Server.create(:network_ids => [network_1.id, network_2.id])
524
+ assert_equal 3, Server.count
525
+ assert_equal 2, network_1.server_count
526
+ assert_equal 1, network_2.server_count
527
+ assert_equal 0, server_1.network_count
528
+ assert_equal 1, server_2.network_count
529
+ assert_equal 2, server_3.network_count
530
+ end
531
+
532
+ should "not count deleted objects" do
533
+ network = Network.create(:klass => "A")
534
+ server = Server.create(:network_ids => [network.id])
535
+ assert_equal 1, network.server_count(:force_reload => true)
536
+ server.delete
537
+ assert_equal 0, network.server_count(:force_reload => true)
538
+ end
539
+
540
+ should "not count deleted objects - from both directions" do
541
+ network = Network.create(:klass => "A")
542
+ server = Server.create(:network_ids => [network.id])
543
+ assert_equal 1, server.network_count(:force_reload => true)
544
+ network.delete
545
+ assert_equal 0, server.network_count(:force_reload => true)
546
+ end
547
+
548
+ end
549
+ end
550
+
551
+ context "with deleted" do
552
+ should "not fetch deleted objects" do
553
+ network = Network.create(:klass => "A")
554
+ server = Server.new
555
+ server.network_ids = [network.id]
556
+ server.save!
557
+ assert_equal 1, network.servers(:force_reload => true).size
558
+ assert_no_difference "Network.count" do
559
+ assert_difference "Server.count", -1 do
560
+ server.delete
561
+ end
562
+ end
563
+ assert_equal 0, network.servers(:force_reload => true).size
564
+ end
565
+
566
+ should "not fetch deleted objects - from both directions" do
567
+ network = Network.create(:klass => "A")
568
+ server = Server.new
569
+ server.network_ids = [network.id]
570
+ server.save!
571
+ assert_equal 1, server.networks(:force_reload => true).size
572
+ assert_difference "Network.count", -1 do
573
+ assert_no_difference "Server.count" do
574
+ network.delete
575
+ end
576
+ end
577
+ assert_equal 0, server.networks(:force_reload => true).size, server.networks(:force_reload => true).inspect
578
+ assert_equal [], server.reload.network_ids
579
+ end
580
+ end
581
+
582
+
583
+ context "with soft deleted" do
584
+
585
+ should "not load soft deleted - items storing keys" do
586
+ network = Network.create
587
+ router = Router.new
588
+ network.add_router(router)
589
+ assert_equal 1, network.routers.size
590
+ router.delete
591
+ assert_equal 0, Router.count
592
+ assert_equal 1, Router.count(:with_deleted => true)
593
+ assert_equal 0, network.routers(:force_reload => true).size
594
+ assert_equal 1, network.routers(:force_reload => true, :with_deleted => true).size
595
+ router.delete!
596
+ assert_equal 0, network.routers(:force_reload => true, :with_deleted => true).size
597
+ end
598
+
599
+ should "not count soft deleted - items storing keys" do
600
+ network = Network.create
601
+ router = Router.new
602
+ network.add_router(router)
603
+ assert_equal 1, network.routers.size
604
+ router.delete
605
+ assert_equal 0, Router.count
606
+ assert_equal 1, Router.count(:with_deleted => true)
607
+ assert_equal 0, network.router_count(:force_reload => true)
608
+ assert_equal 1, network.router_count(:force_reload => true, :with_deleted => true)
609
+ router.delete!
610
+ assert_equal 0, network.router_count(:force_reload => true, :with_deleted => true)
611
+ end
612
+
613
+ should "not load soft deleted - items not storing keys: not supported" do
614
+ book = Book.create
615
+ author = Author.create
616
+ author.add_book(book)
617
+ author.delete
618
+ assert_equal 0, Author.count
619
+ assert_equal 1, Author.count(:with_deleted => true)
620
+ assert_equal 0, book.authors(:force_reload => true).size
621
+ assert_equal 0, book.authors(:force_reload => true, :with_deleted => true).size
622
+ end
623
+
624
+ should "not count soft deleted - items not storing keys: not supported" do
625
+ book = Book.create
626
+ author = Author.create
627
+ author.add_book(book)
628
+ author.delete
629
+ assert_equal 0, Author.count
630
+ assert_equal 1, Author.count(:with_deleted => true)
631
+ assert_equal 0, book.author_count(:force_reload => true)
632
+ assert_equal 0, book.author_count(:force_reload => true, :with_deleted => true)
633
+ end
634
+
635
+ end
636
+
637
+ end
638
+ end
639
+ end
@@ -1,7 +1,7 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
- require File.expand_path(File.dirname(__FILE__) + '/../fixtures/couch')
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/couch')
3
3
 
4
- class CouchHasManyTest < Test::Unit::TestCase
4
+ class HasManyTest < Test::Unit::TestCase
5
5
  context "has_many" do
6
6
  setup do
7
7
  CouchPotato::Config.database_name = 'simply_stored_test'
@@ -13,6 +13,16 @@ class CouchHasManyTest < Test::Unit::TestCase
13
13
  user = User.new
14
14
  assert user.respond_to?(:posts)
15
15
  end
16
+
17
+ should "raise an error if another property with the same name already exists" do
18
+ assert_raise(RuntimeError) do
19
+ class ::DoubleHasManyUser
20
+ include SimplyStored::Couch
21
+ property :other_users
22
+ has_many :other_users
23
+ end
24
+ end
25
+ end
16
26
 
17
27
  should "fetch the associated objects" do
18
28
  user = User.create(:title => "Mr.")
@@ -1,7 +1,7 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
- require File.expand_path(File.dirname(__FILE__) + '/../fixtures/couch')
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/couch')
3
3
 
4
- class CouchHasOneTest < Test::Unit::TestCase
4
+ class HasOneTest < Test::Unit::TestCase
5
5
  context "with has_one" do
6
6
  setup do
7
7
  CouchPotato::Config.database_name = 'simply_stored_test'
@@ -11,6 +11,16 @@ class CouchHasOneTest < Test::Unit::TestCase
11
11
  should "add a getter method" do
12
12
  assert Instance.new.respond_to?(:identity)
13
13
  end
14
+
15
+ should "raise an error if another property with the same name already exists" do
16
+ assert_raise(RuntimeError) do
17
+ class ::DoubleHasOneUser
18
+ include SimplyStored::Couch
19
+ property :user
20
+ has_one :user
21
+ end
22
+ end
23
+ end
14
24
 
15
25
  should "fetch the object when invoking the getter" do
16
26
  instance = Instance.create