toystore 0.5
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/.autotest +11 -0
- data/.bundle/config +2 -0
- data/.gitignore +6 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +49 -0
- data/LICENSE +9 -0
- data/LOGGING.rdoc +16 -0
- data/README.rdoc +13 -0
- data/Rakefile +7 -0
- data/examples/memcached.rb +20 -0
- data/examples/memory.rb +20 -0
- data/examples/models.rb +51 -0
- data/examples/redis.rb +20 -0
- data/lib/toy.rb +81 -0
- data/lib/toy/attribute.rb +73 -0
- data/lib/toy/attributes.rb +137 -0
- data/lib/toy/caching.rb +20 -0
- data/lib/toy/callbacks.rb +48 -0
- data/lib/toy/collection.rb +55 -0
- data/lib/toy/connection.rb +28 -0
- data/lib/toy/dirty.rb +47 -0
- data/lib/toy/dolly.rb +30 -0
- data/lib/toy/embedded_list.rb +45 -0
- data/lib/toy/embedded_lists.rb +68 -0
- data/lib/toy/equality.rb +19 -0
- data/lib/toy/exceptions.rb +29 -0
- data/lib/toy/extensions/array.rb +22 -0
- data/lib/toy/extensions/boolean.rb +43 -0
- data/lib/toy/extensions/date.rb +24 -0
- data/lib/toy/extensions/float.rb +13 -0
- data/lib/toy/extensions/hash.rb +17 -0
- data/lib/toy/extensions/integer.rb +22 -0
- data/lib/toy/extensions/nil_class.rb +17 -0
- data/lib/toy/extensions/object.rb +26 -0
- data/lib/toy/extensions/set.rb +23 -0
- data/lib/toy/extensions/string.rb +17 -0
- data/lib/toy/extensions/time.rb +29 -0
- data/lib/toy/identity.rb +26 -0
- data/lib/toy/identity/abstract_key_factory.rb +10 -0
- data/lib/toy/identity/uuid_key_factory.rb +9 -0
- data/lib/toy/identity_map.rb +109 -0
- data/lib/toy/index.rb +74 -0
- data/lib/toy/indices.rb +56 -0
- data/lib/toy/inspect.rb +12 -0
- data/lib/toy/list.rb +46 -0
- data/lib/toy/lists.rb +37 -0
- data/lib/toy/logger.rb +26 -0
- data/lib/toy/mass_assignment_security.rb +16 -0
- data/lib/toy/persistence.rb +138 -0
- data/lib/toy/plugins.rb +23 -0
- data/lib/toy/proxies/embedded_list.rb +74 -0
- data/lib/toy/proxies/list.rb +97 -0
- data/lib/toy/proxies/proxy.rb +59 -0
- data/lib/toy/querying.rb +57 -0
- data/lib/toy/reference.rb +134 -0
- data/lib/toy/references.rb +19 -0
- data/lib/toy/serialization.rb +81 -0
- data/lib/toy/store.rb +36 -0
- data/lib/toy/timestamps.rb +22 -0
- data/lib/toy/validations.rb +45 -0
- data/lib/toy/version.rb +3 -0
- data/lib/toystore.rb +1 -0
- data/spec/helper.rb +35 -0
- data/spec/spec.opts +3 -0
- data/spec/support/constants.rb +41 -0
- data/spec/support/identity_map_matcher.rb +20 -0
- data/spec/support/name_and_number_key_factory.rb +5 -0
- data/spec/toy/attribute_spec.rb +176 -0
- data/spec/toy/attributes_spec.rb +394 -0
- data/spec/toy/caching_spec.rb +62 -0
- data/spec/toy/callbacks_spec.rb +97 -0
- data/spec/toy/connection_spec.rb +47 -0
- data/spec/toy/dirty_spec.rb +99 -0
- data/spec/toy/dolly_spec.rb +76 -0
- data/spec/toy/embedded_list_spec.rb +607 -0
- data/spec/toy/embedded_lists_spec.rb +172 -0
- data/spec/toy/equality_spec.rb +46 -0
- data/spec/toy/exceptions_spec.rb +18 -0
- data/spec/toy/extensions/array_spec.rb +25 -0
- data/spec/toy/extensions/boolean_spec.rb +41 -0
- data/spec/toy/extensions/date_spec.rb +48 -0
- data/spec/toy/extensions/float_spec.rb +14 -0
- data/spec/toy/extensions/hash_spec.rb +21 -0
- data/spec/toy/extensions/integer_spec.rb +29 -0
- data/spec/toy/extensions/nil_class_spec.rb +14 -0
- data/spec/toy/extensions/set_spec.rb +27 -0
- data/spec/toy/extensions/string_spec.rb +28 -0
- data/spec/toy/extensions/time_spec.rb +94 -0
- data/spec/toy/identity/abstract_key_factory_spec.rb +7 -0
- data/spec/toy/identity/uuid_key_factory_spec.rb +7 -0
- data/spec/toy/identity_map_spec.rb +150 -0
- data/spec/toy/identity_spec.rb +52 -0
- data/spec/toy/index_spec.rb +230 -0
- data/spec/toy/indices_spec.rb +141 -0
- data/spec/toy/inspect_spec.rb +15 -0
- data/spec/toy/list_spec.rb +576 -0
- data/spec/toy/lists_spec.rb +95 -0
- data/spec/toy/logger_spec.rb +33 -0
- data/spec/toy/mass_assignment_security_spec.rb +116 -0
- data/spec/toy/persistence_spec.rb +312 -0
- data/spec/toy/plugins_spec.rb +39 -0
- data/spec/toy/querying_spec.rb +162 -0
- data/spec/toy/reference_spec.rb +400 -0
- data/spec/toy/references_spec.rb +86 -0
- data/spec/toy/serialization_spec.rb +354 -0
- data/spec/toy/store_spec.rb +41 -0
- data/spec/toy/timestamps_spec.rb +63 -0
- data/spec/toy/validations_spec.rb +171 -0
- data/spec/toy_spec.rb +26 -0
- data/specs.watchr +52 -0
- data/test/lint_test.rb +40 -0
- data/toystore.gemspec +24 -0
- 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
|