toystore 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/.autotest +11 -0
  2. data/.bundle/config +2 -0
  3. data/.gitignore +6 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +49 -0
  6. data/LICENSE +9 -0
  7. data/LOGGING.rdoc +16 -0
  8. data/README.rdoc +13 -0
  9. data/Rakefile +7 -0
  10. data/examples/memcached.rb +20 -0
  11. data/examples/memory.rb +20 -0
  12. data/examples/models.rb +51 -0
  13. data/examples/redis.rb +20 -0
  14. data/lib/toy.rb +81 -0
  15. data/lib/toy/attribute.rb +73 -0
  16. data/lib/toy/attributes.rb +137 -0
  17. data/lib/toy/caching.rb +20 -0
  18. data/lib/toy/callbacks.rb +48 -0
  19. data/lib/toy/collection.rb +55 -0
  20. data/lib/toy/connection.rb +28 -0
  21. data/lib/toy/dirty.rb +47 -0
  22. data/lib/toy/dolly.rb +30 -0
  23. data/lib/toy/embedded_list.rb +45 -0
  24. data/lib/toy/embedded_lists.rb +68 -0
  25. data/lib/toy/equality.rb +19 -0
  26. data/lib/toy/exceptions.rb +29 -0
  27. data/lib/toy/extensions/array.rb +22 -0
  28. data/lib/toy/extensions/boolean.rb +43 -0
  29. data/lib/toy/extensions/date.rb +24 -0
  30. data/lib/toy/extensions/float.rb +13 -0
  31. data/lib/toy/extensions/hash.rb +17 -0
  32. data/lib/toy/extensions/integer.rb +22 -0
  33. data/lib/toy/extensions/nil_class.rb +17 -0
  34. data/lib/toy/extensions/object.rb +26 -0
  35. data/lib/toy/extensions/set.rb +23 -0
  36. data/lib/toy/extensions/string.rb +17 -0
  37. data/lib/toy/extensions/time.rb +29 -0
  38. data/lib/toy/identity.rb +26 -0
  39. data/lib/toy/identity/abstract_key_factory.rb +10 -0
  40. data/lib/toy/identity/uuid_key_factory.rb +9 -0
  41. data/lib/toy/identity_map.rb +109 -0
  42. data/lib/toy/index.rb +74 -0
  43. data/lib/toy/indices.rb +56 -0
  44. data/lib/toy/inspect.rb +12 -0
  45. data/lib/toy/list.rb +46 -0
  46. data/lib/toy/lists.rb +37 -0
  47. data/lib/toy/logger.rb +26 -0
  48. data/lib/toy/mass_assignment_security.rb +16 -0
  49. data/lib/toy/persistence.rb +138 -0
  50. data/lib/toy/plugins.rb +23 -0
  51. data/lib/toy/proxies/embedded_list.rb +74 -0
  52. data/lib/toy/proxies/list.rb +97 -0
  53. data/lib/toy/proxies/proxy.rb +59 -0
  54. data/lib/toy/querying.rb +57 -0
  55. data/lib/toy/reference.rb +134 -0
  56. data/lib/toy/references.rb +19 -0
  57. data/lib/toy/serialization.rb +81 -0
  58. data/lib/toy/store.rb +36 -0
  59. data/lib/toy/timestamps.rb +22 -0
  60. data/lib/toy/validations.rb +45 -0
  61. data/lib/toy/version.rb +3 -0
  62. data/lib/toystore.rb +1 -0
  63. data/spec/helper.rb +35 -0
  64. data/spec/spec.opts +3 -0
  65. data/spec/support/constants.rb +41 -0
  66. data/spec/support/identity_map_matcher.rb +20 -0
  67. data/spec/support/name_and_number_key_factory.rb +5 -0
  68. data/spec/toy/attribute_spec.rb +176 -0
  69. data/spec/toy/attributes_spec.rb +394 -0
  70. data/spec/toy/caching_spec.rb +62 -0
  71. data/spec/toy/callbacks_spec.rb +97 -0
  72. data/spec/toy/connection_spec.rb +47 -0
  73. data/spec/toy/dirty_spec.rb +99 -0
  74. data/spec/toy/dolly_spec.rb +76 -0
  75. data/spec/toy/embedded_list_spec.rb +607 -0
  76. data/spec/toy/embedded_lists_spec.rb +172 -0
  77. data/spec/toy/equality_spec.rb +46 -0
  78. data/spec/toy/exceptions_spec.rb +18 -0
  79. data/spec/toy/extensions/array_spec.rb +25 -0
  80. data/spec/toy/extensions/boolean_spec.rb +41 -0
  81. data/spec/toy/extensions/date_spec.rb +48 -0
  82. data/spec/toy/extensions/float_spec.rb +14 -0
  83. data/spec/toy/extensions/hash_spec.rb +21 -0
  84. data/spec/toy/extensions/integer_spec.rb +29 -0
  85. data/spec/toy/extensions/nil_class_spec.rb +14 -0
  86. data/spec/toy/extensions/set_spec.rb +27 -0
  87. data/spec/toy/extensions/string_spec.rb +28 -0
  88. data/spec/toy/extensions/time_spec.rb +94 -0
  89. data/spec/toy/identity/abstract_key_factory_spec.rb +7 -0
  90. data/spec/toy/identity/uuid_key_factory_spec.rb +7 -0
  91. data/spec/toy/identity_map_spec.rb +150 -0
  92. data/spec/toy/identity_spec.rb +52 -0
  93. data/spec/toy/index_spec.rb +230 -0
  94. data/spec/toy/indices_spec.rb +141 -0
  95. data/spec/toy/inspect_spec.rb +15 -0
  96. data/spec/toy/list_spec.rb +576 -0
  97. data/spec/toy/lists_spec.rb +95 -0
  98. data/spec/toy/logger_spec.rb +33 -0
  99. data/spec/toy/mass_assignment_security_spec.rb +116 -0
  100. data/spec/toy/persistence_spec.rb +312 -0
  101. data/spec/toy/plugins_spec.rb +39 -0
  102. data/spec/toy/querying_spec.rb +162 -0
  103. data/spec/toy/reference_spec.rb +400 -0
  104. data/spec/toy/references_spec.rb +86 -0
  105. data/spec/toy/serialization_spec.rb +354 -0
  106. data/spec/toy/store_spec.rb +41 -0
  107. data/spec/toy/timestamps_spec.rb +63 -0
  108. data/spec/toy/validations_spec.rb +171 -0
  109. data/spec/toy_spec.rb +26 -0
  110. data/specs.watchr +52 -0
  111. data/test/lint_test.rb +40 -0
  112. data/toystore.gemspec +24 -0
  113. metadata +290 -0
@@ -0,0 +1,141 @@
1
+ require 'helper'
2
+
3
+ describe Toy::Indices do
4
+ uses_constants('User')
5
+
6
+ it "defaults lists to empty hash" do
7
+ User.indices.should == {}
8
+ end
9
+
10
+ describe "declaring a list" do
11
+ before do
12
+ User.attribute :ssn, String
13
+ @index = User.index(:ssn)
14
+ end
15
+
16
+ it "knows about its lists" do
17
+ User.indices[:ssn].should == Toy::Index.new(User, :ssn)
18
+ end
19
+
20
+ it "returns list" do
21
+ @index.should == Toy::Index.new(User, :ssn)
22
+ end
23
+
24
+ it "adds indices instance method" do
25
+ User.new.indices.should == User.indices
26
+ end
27
+ end
28
+
29
+ describe ".index_key" do
30
+ it "returns key if index exists" do
31
+ sha = Digest::SHA1.hexdigest('taco@bell.com')
32
+ User.attribute(:email, String)
33
+ User.index(:email)
34
+ User.index_key(:email, 'taco@bell.com').should == "User:email:#{sha}"
35
+ end
36
+
37
+ it "works with string name" do
38
+ sha = Digest::SHA1.hexdigest('taco@bell.com')
39
+ User.attribute(:email, String)
40
+ User.index(:email)
41
+ User.index_key('email', 'taco@bell.com').should == "User:email:#{sha}"
42
+ end
43
+
44
+ it "raises error if index does not exist" do
45
+ lambda {
46
+ User.index_key(:email, 'taco@bell.com')
47
+ }.should raise_error(ArgumentError, 'Index for email does not exist')
48
+ end
49
+ end
50
+
51
+ describe ".get_index (existing)" do
52
+ before do
53
+ User.attribute(:email, String)
54
+ User.index(:email)
55
+ User.create_index(:email, 'taco@bell.com', 1)
56
+ User.create_index(:email, 'taco@bell.com', 2)
57
+ @index = User.get_index(:email, 'taco@bell.com')
58
+ end
59
+
60
+ it "returns decoded array" do
61
+ @index.should == [1, 2]
62
+ end
63
+ end
64
+
65
+ describe ".get_index (missing)" do
66
+ before do
67
+ User.attribute(:email, String)
68
+ User.index(:email)
69
+ @index = User.get_index(:email, 'taco@bell.com')
70
+ end
71
+
72
+ it "returns empty array" do
73
+ @index.should == []
74
+ end
75
+ end
76
+
77
+ describe ".create_index (single value)" do
78
+ before do
79
+ User.attribute(:email, String)
80
+ User.index(:email)
81
+ User.create_index(:email, 'taco@bell.com', 1)
82
+ end
83
+
84
+ it "stores id in array" do
85
+ User.get_index(:email, 'taco@bell.com').should == [1]
86
+ end
87
+ end
88
+
89
+ describe ".create_index (multiple values)" do
90
+ before do
91
+ User.attribute(:email, String)
92
+ User.index(:email)
93
+ User.create_index(:email, 'taco@bell.com', 1)
94
+ User.create_index(:email, 'taco@bell.com', 2)
95
+ User.create_index(:email, 'taco@bell.com', 3)
96
+ end
97
+
98
+ it "stores each value in array" do
99
+ User.get_index(:email, 'taco@bell.com').should == [1, 2, 3]
100
+ end
101
+ end
102
+
103
+ describe ".create_index (same value multiple times)" do
104
+ before do
105
+ User.attribute(:email, String)
106
+ User.index(:email)
107
+ User.create_index(:email, 'taco@bell.com', 1)
108
+ User.create_index(:email, 'taco@bell.com', 2)
109
+ User.create_index(:email, 'taco@bell.com', 1)
110
+ end
111
+
112
+ it "stores value only once and doesn't change order" do
113
+ User.get_index(:email, 'taco@bell.com').should == [1, 2]
114
+ end
115
+ end
116
+
117
+ describe ".destroy_index (for missing index)" do
118
+ before do
119
+ User.attribute(:email, String)
120
+ User.index(:email)
121
+ User.destroy_index(:email, 'taco@bell.com', 1)
122
+ end
123
+
124
+ it "sets index to empty array" do
125
+ User.get_index(:email, 'taco@bell.com').should == []
126
+ end
127
+ end
128
+
129
+ describe ".destroy_index (for indexed id)" do
130
+ before do
131
+ User.attribute(:email, String)
132
+ User.index(:email)
133
+ User.create_index(:email, 'taco@bell.com', 1)
134
+ User.destroy_index(:email, 'taco@bell.com', 1)
135
+ end
136
+
137
+ it "removes the value from the index" do
138
+ User.get_index(:email, 'taco@bell.com').should == []
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,15 @@
1
+ require 'helper'
2
+
3
+ describe Toy::Attributes do
4
+ uses_constants('User')
5
+
6
+ before do
7
+ User.attribute(:name, String)
8
+ User.attribute(:age, Integer)
9
+ end
10
+
11
+ it "prints out object id and attributes sorted with values" do
12
+ user = User.new(:age => 28, :name => 'John')
13
+ user.inspect.should == %Q(#<User:#{user.object_id} age: 28, id: "#{user.id}", name: "John">)
14
+ end
15
+ end
@@ -0,0 +1,576 @@
1
+ require 'helper'
2
+
3
+ describe Toy::List do
4
+ uses_constants('User', 'Game', 'Move', 'Chat', 'Contact')
5
+
6
+ before do
7
+ @list = User.list(:games)
8
+ end
9
+
10
+ let(:list) { @list }
11
+
12
+ it "has model" do
13
+ list.model.should == User
14
+ end
15
+
16
+ it "has name" do
17
+ list.name.should == :games
18
+ end
19
+
20
+ it "has type" do
21
+ list.type.should == Game
22
+ end
23
+
24
+ it "has key" do
25
+ list.key.should == :game_ids
26
+ end
27
+
28
+ it "has instance_variable" do
29
+ list.instance_variable.should == :@_games
30
+ end
31
+
32
+ it "adds list to model" do
33
+ User.lists.keys.should include(:games)
34
+ end
35
+
36
+ it "adds attribute to model" do
37
+ User.attributes.keys.should include('game_ids')
38
+ end
39
+
40
+ it "adds reader method" do
41
+ User.new.should respond_to(:games)
42
+ end
43
+
44
+ it "adds writer method" do
45
+ User.new.should respond_to(:games=)
46
+ end
47
+
48
+ describe "#eql?" do
49
+ it "returns true if same class, model, and name" do
50
+ list.should eql(list)
51
+ end
52
+
53
+ it "returns false if not same class" do
54
+ list.should_not eql({})
55
+ end
56
+
57
+ it "returns false if not same model" do
58
+ list.should_not eql(Toy::List.new(Game, :users))
59
+ end
60
+
61
+ it "returns false if not the same name" do
62
+ list.should_not eql(Toy::List.new(User, :moves))
63
+ end
64
+ end
65
+
66
+ describe "dependent" do
67
+ before do
68
+ User.list :games, :dependent => true
69
+ @game = Game.create
70
+ @user = User.create(:game_ids => [@game.id])
71
+ end
72
+
73
+ it "should create a method to destroy games" do
74
+ User.new.should respond_to(:destroy_games)
75
+ end
76
+
77
+ it "should remove the games" do
78
+ user_id = @user.id
79
+ game_id = @game.id
80
+ @user.destroy
81
+ User.get(user_id).should be_nil
82
+ Game.get(game_id).should be_nil
83
+ end
84
+ end
85
+
86
+ describe "setting list type" do
87
+ before do
88
+ @list = User.list(:active_games, Game)
89
+ end
90
+ let(:list) { @list }
91
+
92
+ it "uses type provided instead of inferring from name" do
93
+ list.type.should be(Game)
94
+ end
95
+
96
+ it "works properly when reading and writing" do
97
+ user = User.create
98
+ game = Game.create
99
+ user.active_games = [game]
100
+ user.active_games.should == [game]
101
+ end
102
+ end
103
+
104
+ describe "list reader" do
105
+ before do
106
+ @game = Game.create
107
+ @user = User.create(:game_ids => [@game.id])
108
+ end
109
+
110
+ it "returns instances" do
111
+ @user.games.should == [@game]
112
+ end
113
+
114
+ it "memoizes result" do
115
+ @user.games.should == [@game]
116
+ Game.should_not_receive(:get_multi)
117
+ Game.should_not_receive(:get)
118
+ @user.games.should == [@game]
119
+ end
120
+
121
+ it "does not query if ids attribute is blank" do
122
+ user = User.create
123
+ Game.should_not_receive(:get_multi)
124
+ Game.should_not_receive(:get)
125
+ user.games.should == []
126
+ end
127
+ end
128
+
129
+ describe "list writer (with instances)" do
130
+ before do
131
+ @game1 = Game.create
132
+ @game2 = Game.create
133
+ @user = User.create(:game_ids => [@game1.id])
134
+ @user.games = [@game2]
135
+ end
136
+
137
+ it "set attribute" do
138
+ @user.game_ids.should == [@game2.id]
139
+ end
140
+
141
+ it "unmemoizes reader" do
142
+ @user.games.should == [@game2]
143
+ @user.games = [@game1]
144
+ @user.games.should == [@game1]
145
+ end
146
+ end
147
+
148
+ describe "list#reset" do
149
+ before do
150
+ @game = Game.create
151
+ @user = User.create(:game_ids => [@game.id])
152
+ end
153
+
154
+ it "unmemoizes the list" do
155
+ games = [@game]
156
+ @user.games.should == games
157
+ @user.games.reset
158
+ Game.should_receive(:get_multi).and_return(games)
159
+ @user.games.should == games
160
+ end
161
+
162
+ it "should be reset when owner is reloaded" do
163
+ games = [@game]
164
+ @user.games.should == games
165
+ @user.reload
166
+ Game.should_receive(:get_multi).and_return(games)
167
+ @user.games.should == games
168
+ end
169
+ end
170
+
171
+ describe "list#push" do
172
+ before do
173
+ @game = Game.create
174
+ @user = User.create
175
+ @user.games.push(@game)
176
+ end
177
+
178
+ it "adds id to attribute" do
179
+ @user.game_ids.should == [@game.id]
180
+ end
181
+
182
+ it "resets association" do
183
+ @user.games.should == [@game]
184
+ end
185
+
186
+ it "raises error if wrong type assigned" do
187
+ lambda {
188
+ @user.games.push(Move.new)
189
+ }.should raise_error(ArgumentError, "Game expected, but was Move")
190
+ end
191
+ end
192
+
193
+ describe "list#<<" do
194
+ before do
195
+ @game = Game.create
196
+ @user = User.create
197
+ @user.games << @game
198
+ end
199
+
200
+ it "adds id to attribute" do
201
+ @user.game_ids.should == [@game.id]
202
+ end
203
+
204
+ it "raises error if wrong type assigned" do
205
+ lambda {
206
+ @user.games << Move.new
207
+ }.should raise_error(ArgumentError, "Game expected, but was Move")
208
+ end
209
+ end
210
+
211
+ describe "list#concat" do
212
+ before do
213
+ @game1 = Game.create
214
+ @game2 = Game.create
215
+ @user = User.create
216
+ @user.games.concat(@game1, @game2)
217
+ end
218
+
219
+ it "adds id to attribute" do
220
+ @user.game_ids.should == [@game1.id, @game2.id]
221
+ end
222
+
223
+ it "raises error if wrong type assigned" do
224
+ lambda {
225
+ @user.games.concat(Move.new)
226
+ }.should raise_error(ArgumentError, "Game expected, but was Move")
227
+ end
228
+ end
229
+
230
+ describe "list#concat (with array)" do
231
+ before do
232
+ @game1 = Game.create
233
+ @game2 = Game.create
234
+ @user = User.create
235
+ @user.games.concat([@game1, @game2])
236
+ end
237
+
238
+ it "adds id to attribute" do
239
+ @user.game_ids.should == [@game1.id, @game2.id]
240
+ end
241
+
242
+ it "raises error if wrong type assigned" do
243
+ lambda {
244
+ @user.games.concat([Move.new])
245
+ }.should raise_error(ArgumentError, "Game expected, but was Move")
246
+ end
247
+ end
248
+
249
+ shared_examples_for("list#create") do
250
+ it "creates instance" do
251
+ @game.should be_persisted
252
+ end
253
+
254
+ it "adds id to attribute" do
255
+ @user.game_ids.should == [@game.id]
256
+ end
257
+
258
+ it "adds instance to reader" do
259
+ @user.games.should == [@game]
260
+ end
261
+ end
262
+
263
+ describe "list#create" do
264
+ before do
265
+ @user = User.create
266
+ @game = @user.games.create
267
+ end
268
+
269
+ it_should_behave_like "list#create"
270
+ end
271
+
272
+ describe "list#create (with attributes)" do
273
+ before do
274
+ Game.attribute(:move_count, Integer)
275
+ @user = User.create
276
+ @game = @user.games.create(:move_count => 10)
277
+ end
278
+
279
+ it_should_behave_like "list#create"
280
+
281
+ it "sets attributes on instance" do
282
+ @game.move_count.should == 10
283
+ end
284
+ end
285
+
286
+ describe "list#create (invalid)" do
287
+ before do
288
+ @user = User.create
289
+ @user.games.should_not_receive(:push)
290
+ @user.games.should_not_receive(:reset)
291
+ @user.should_not_receive(:reload)
292
+ @user.should_not_receive(:save)
293
+
294
+ Game.attribute(:move_count, Integer)
295
+ Game.validates_presence_of(:move_count)
296
+
297
+ @game = @user.games.create
298
+ end
299
+
300
+ it "returns instance" do
301
+ @game.should be_instance_of(Game)
302
+ end
303
+
304
+ it "is not persisted" do
305
+ @game.should_not be_persisted
306
+ end
307
+ end
308
+
309
+ describe "list#create (with :inverse_of)" do
310
+ before do
311
+ Chat.reference(:game, Game)
312
+ Game.list(:chats, Chat, :inverse_of => :game)
313
+ @game = Game.create
314
+ @chat = @game.chats.create
315
+ end
316
+
317
+ it "sets the inverse association" do
318
+ # @game.chats.should include(@chat)
319
+ @chat.game.should == @game
320
+ end
321
+ end
322
+
323
+ describe "list#create (with callbacks)" do
324
+ it "should not overwrite changes made in callbacks of list item" do
325
+ User.attribute :chat_count, Integer, :default => 0
326
+ User.list :chats, :inverse_of => :user
327
+ Chat.reference(:user)
328
+ Chat.class_eval do
329
+ after_create :increment_user_chat_count
330
+ def increment_user_chat_count
331
+ self.user.update_attributes(:chat_count => 1)
332
+ end
333
+ end
334
+
335
+ @user = User.create
336
+ @user.chat_count.should == 0
337
+
338
+ chat = @user.chats.create
339
+
340
+ chat.user.should == @user
341
+ @user.chats.count.should == 1
342
+ @user.chat_count.should == 1
343
+ end
344
+
345
+ it "should be able to create list item in a callback" do
346
+ Contact.reference(:user)
347
+ User.list(:contacts, :inverse_of => :user)
348
+ User.class_eval do
349
+ after_create :create_initial_contact
350
+ def create_initial_contact
351
+ contacts.create
352
+ end
353
+ end
354
+
355
+ user = User.create
356
+ user.contacts.count.should == 1
357
+ end
358
+ end
359
+
360
+ describe "list#destroy" do
361
+ before do
362
+ @user = User.create
363
+ @game1 = @user.games.create
364
+ @game2 = @user.games.create
365
+ User.get(@user.id).games.should == [@game1, @game2]
366
+ end
367
+
368
+ it "should take multiple ids" do
369
+ @user.games.destroy(@game1.id, @game2.id)
370
+
371
+ User.get(@user.id).games.should be_empty
372
+ Game.get(@game1.id).should be_nil
373
+ Game.get(@game2.id).should be_nil
374
+ end
375
+
376
+ it "should take an array of ids" do
377
+ @user.games.destroy([@game1.id, @game2.id])
378
+
379
+ User.get(@user.id).games.should be_empty
380
+ Game.get(@game1.id).should be_nil
381
+ Game.get(@game2.id).should be_nil
382
+ end
383
+
384
+ it "should take a block to filter on" do
385
+ Game.attribute :active, Boolean
386
+ @game1.update_attributes(:active => true)
387
+ @game2.update_attributes(:active => false)
388
+
389
+ @user.games.destroy { |g| g.active == true }
390
+
391
+ User.get(@user.id).games.should == [@game2]
392
+ Game.get(@game1.id).should be_nil
393
+ end
394
+
395
+ it "should not override changes make in callbacks" do
396
+ User.attribute :chat_count, Integer, :default => 1
397
+ User.list :chats, :inverse_of => :user
398
+
399
+ Chat.reference :user
400
+ Chat.class_eval do
401
+ after_destroy :decrement_user_chat_count
402
+ def decrement_user_chat_count
403
+ user.update_attributes(:chat_count => 0)
404
+ end
405
+ end
406
+
407
+ user = User.create
408
+ user.chat_count.should == 1
409
+ chat = user.chats.create
410
+ user.chats.destroy(chat.id)
411
+ user.chat_count.should == 0
412
+ end
413
+ end
414
+
415
+ describe "list#destroy_all" do
416
+ before do
417
+ @user = User.create
418
+ @game1 = @user.games.create
419
+ @game2 = @user.games.create
420
+ User.get(@user.id).games.should == [@game1, @game2]
421
+ end
422
+
423
+ it "should destroy all" do
424
+ @user.games.destroy_all
425
+
426
+ User.get(@user.id).games.should be_empty
427
+ Game.get(@game1.id).should be_nil
428
+ Game.get(@game2.id).should be_nil
429
+ end
430
+ end
431
+
432
+ describe "list#each" do
433
+ before do
434
+ @game1 = Game.create
435
+ @game2 = Game.create
436
+ @user = User.create(:game_ids => [@game1.id, @game2.id])
437
+ end
438
+
439
+ it "iterates through each instance" do
440
+ games = []
441
+ @user.games.each do |game|
442
+ games << game
443
+ end
444
+ games.should == [@game1, @game2]
445
+ end
446
+ end
447
+
448
+ describe "enumerating" do
449
+ before do
450
+ Game.attribute(:moves, Integer)
451
+ @game1 = Game.create(:moves => 1)
452
+ @game2 = Game.create(:moves => 2)
453
+ @user = User.create(:game_ids => [@game1.id, @game2.id])
454
+ end
455
+
456
+ it "works" do
457
+ @user.games.select { |g| g.moves > 1 }.should == [@game2]
458
+ @user.games.reject { |g| g.moves > 1 }.should == [@game1]
459
+ end
460
+ end
461
+
462
+ describe "list#include?" do
463
+ before do
464
+ @game1 = Game.create
465
+ @game2 = Game.create
466
+ @user = User.create(:game_ids => [@game1.id])
467
+ end
468
+
469
+ it "returns true if instance in association" do
470
+ @user.games.should include(@game1)
471
+ end
472
+
473
+ it "returns false if instance not in association" do
474
+ @user.games.should_not include(@game2)
475
+ end
476
+
477
+ it "returns false for nil" do
478
+ @user.games.should_not include(nil)
479
+ end
480
+ end
481
+
482
+ describe "list with block" do
483
+ before do
484
+ Move.attribute(:old, Boolean)
485
+ User.list(:moves) do
486
+ def old
487
+ target.select { |m| m.old? }
488
+ end
489
+ end
490
+
491
+ @move_new = Move.create(:old => false)
492
+ @move_old = Move.create(:old => true)
493
+ @user = User.create(:moves => [@move_new, @move_old])
494
+ end
495
+
496
+ it "extends block methods onto proxy" do
497
+ @user.moves.respond_to?(:old).should be_true
498
+ @user.moves.old.should == [@move_old]
499
+ end
500
+ end
501
+
502
+ describe "list extension with :extensions option" do
503
+ before do
504
+ old_module = Module.new do
505
+ def old
506
+ target.select { |m| m.old? }
507
+ end
508
+ end
509
+
510
+ recent_proc = Proc.new do
511
+ def recent
512
+ target.select { |m| !m.old? }
513
+ end
514
+ end
515
+
516
+ Move.attribute(:old, Boolean)
517
+ User.list(:moves, :extensions => [old_module, recent_proc])
518
+
519
+ @move_new = Move.create(:old => false)
520
+ @move_old = Move.create(:old => true)
521
+ @user = User.create(:moves => [@move_new, @move_old])
522
+ end
523
+
524
+ it "extends modules" do
525
+ @user.moves.respond_to?(:old).should be_true
526
+ @user.moves.old.should == [@move_old]
527
+ end
528
+
529
+ it "extends procs" do
530
+ @user.moves.respond_to?(:recent).should be_true
531
+ @user.moves.recent.should == [@move_new]
532
+ end
533
+ end
534
+
535
+ describe "list#get" do
536
+ before do
537
+ @user = User.create
538
+ @game = @user.games.create
539
+ end
540
+
541
+ it "should not find items that don't exist" do
542
+ @user.games.get('does-not-exist').should be_nil
543
+ end
544
+
545
+ it "should not find items that exist but are not in list" do
546
+ user = User.create
547
+ user.games.get(@game.id).should be_nil
548
+ end
549
+
550
+ it "should find items that are in list" do
551
+ @user.games.get(@game.id).should == @game
552
+ end
553
+
554
+ it "should only perform one get to find the item if present" do
555
+ Game.should_receive(:get).once
556
+ @user.games.get(@game.id)
557
+ end
558
+ end
559
+
560
+ describe "list#get!" do
561
+ before do
562
+ @user = User.create
563
+ @game = @user.games.create
564
+ end
565
+
566
+ it "returns game if found" do
567
+ lambda {
568
+ @user.games.get!('does-not-exist')
569
+ }.should raise_error(Toy::NotFound, 'Could not find document with id: "does-not-exist"')
570
+ end
571
+
572
+ it "raises exception if not found" do
573
+ @user.games.get!(@game.id).should == @game
574
+ end
575
+ end
576
+ end