mongodb 0.0.1 → 0.0.2
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/Rakefile +3 -5
- data/lib/mongodb/driver.rb +33 -0
- data/lib/mongodb/driver/collection.rb +156 -0
- data/lib/mongodb/driver/database.rb +6 -0
- data/lib/mongodb/driver/dynamic_finders.rb +41 -0
- data/lib/{mongo_db → mongodb}/driver/spec.rb +12 -12
- data/lib/mongodb/gems.rb +6 -0
- data/lib/mongodb/integration/locales.rb +4 -0
- data/lib/mongodb/integration/locales/activemodel/ru.yml +27 -0
- data/lib/mongodb/migration.rb +8 -0
- data/lib/mongodb/migration/definition.rb +19 -0
- data/lib/mongodb/migration/migration.rb +68 -0
- data/lib/mongodb/migration/tasks.rb +19 -0
- data/lib/mongodb/model.rb +26 -0
- data/lib/mongodb/model/assignment.rb +65 -0
- data/lib/mongodb/model/attribute_convertors.rb +54 -0
- data/lib/mongodb/model/callbacks.rb +36 -0
- data/lib/mongodb/model/crud.rb +57 -0
- data/lib/mongodb/model/db.rb +53 -0
- data/lib/mongodb/model/misc.rb +33 -0
- data/lib/mongodb/model/model.rb +11 -0
- data/lib/mongodb/model/query.rb +36 -0
- data/lib/mongodb/model/scope.rb +99 -0
- data/lib/mongodb/model/spec.rb +12 -0
- data/lib/mongodb/model/support/types.rb +110 -0
- data/lib/mongodb/model/validation.rb +5 -0
- data/lib/mongodb/object.rb +18 -0
- data/lib/mongodb/object/object_helper.rb +62 -0
- data/lib/mongodb/object/object_serializer.rb +273 -0
- data/readme.md +261 -6
- data/spec/driver/collection_spec.rb +83 -0
- data/spec/{mongo_model/hash → driver}/crud_spec.rb +30 -29
- data/spec/driver/database_spec.rb +9 -0
- data/spec/driver/dynamic_finders_spec.rb +50 -0
- data/spec/driver/fixes_spec.rb +12 -0
- data/spec/driver/hash_helper_spec.rb +24 -0
- data/spec/driver/spec_helper.rb +28 -0
- data/spec/integration/am_conversion_spec.rb +1 -0
- data/spec/integration/am_validation_spec.rb +34 -0
- data/spec/integration/validatable2_spec.rb +40 -0
- data/spec/migration/migration_spec.rb +60 -0
- data/spec/model/assignment_spec.rb +80 -0
- data/spec/model/attribute_convertors_spec.rb +73 -0
- data/spec/model/callbacks_spec.rb +47 -0
- data/spec/model/crud_spec.rb +151 -0
- data/spec/model/db_spec.rb +63 -0
- data/spec/model/misc_spec.rb +58 -0
- data/spec/model/query_spec.rb +47 -0
- data/spec/model/scope_spec.rb +149 -0
- data/spec/model/spec_helper.rb +4 -0
- data/spec/model/validation_spec.rb +37 -0
- data/spec/object/callbacks_spec.rb +97 -0
- data/spec/object/crud_shared.rb +53 -0
- data/spec/object/crud_spec.rb +55 -0
- data/spec/object/spec_helper.rb +14 -0
- data/spec/{mongo_model/object → object}/validation_spec.rb +38 -36
- metadata +92 -25
- data/lib/mongo_db.rb +0 -3
- data/lib/mongo_db/driver.rb +0 -5
- data/lib/mongo_db/driver/connection.rb +0 -0
- data/lib/mongo_db/driver/database.rb +0 -5
- data/lib/mongo_db/gems.rb +0 -2
- data/lib/mongo_db/model.rb +0 -0
- data/spec/mongo_ext/migration_spec.rb +0 -0
- data/spec/mongo_ext/misc_spec.rb +0 -10
- data/spec/mongo_ext/spec_helper.rb +0 -4
- data/spec/mongo_model/model/crud_spec.rb +0 -123
- data/spec/mongo_model/model/query_spec.rb +0 -0
- data/spec/mongo_model/object/callbacks_spec.rb +0 -100
- data/spec/mongo_model/object/crud_shared.rb +0 -53
- data/spec/mongo_model/object/crud_spec.rb +0 -45
- data/spec/mongo_model/spec_helper.rb +0 -1
- data/spec/query_spec.rb +0 -0
- data/spec/test_spec.rb +0 -5
data/readme.md
CHANGED
@@ -1,9 +1,264 @@
|
|
1
|
-
|
1
|
+
Object Model & Ruby driver enhancements for MongoDB.
|
2
2
|
|
3
|
-
|
3
|
+
1. Driver enchancements & Migrations.
|
4
|
+
2. Persistence for any Ruby object.
|
5
|
+
3. Object Model (callbacks, validations, mass-assignment, finders, ...).
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
Lower layers are independent from upper, use only what You need.
|
8
|
+
|
9
|
+
# MongoDB driver enhancements
|
10
|
+
|
11
|
+
MongoDB itself is very powerful, flexible and simple tool, but the API of the Ruby driver is a little complicated.
|
12
|
+
These enhancements alter the driver's API and made it more simple and intuitive.
|
13
|
+
|
14
|
+
- Makes API of mongo-ruby-driver friendly & handy.
|
15
|
+
- No extra abstraction or complexities introduced, all things are exactly the same as in MongoDB.
|
16
|
+
- 100% backward compatibility with original driver API (if not - it's a bug, report it please)
|
17
|
+
|
18
|
+
``` ruby
|
19
|
+
require 'mongodb/driver'
|
20
|
+
|
21
|
+
# Changing some defaults.
|
22
|
+
Mongo.defaults.merge! symbolize: true, multi: true, safe: true
|
23
|
+
|
24
|
+
# Connection & db.
|
25
|
+
connection = Mongo::Connection.new
|
26
|
+
db = connection.db 'default_test'
|
27
|
+
db.units.drop
|
28
|
+
|
29
|
+
# Collection shortcuts.
|
30
|
+
db.some_collection
|
31
|
+
|
32
|
+
# Create.
|
33
|
+
zeratul = {name: 'Zeratul', stats: {attack: 85, life: 300, shield: 100}}
|
34
|
+
tassadar = {name: 'Tassadar', stats: {attack: 0, life: 80, shield: 300}}
|
35
|
+
|
36
|
+
db.units.save zeratul
|
37
|
+
db.units.save tassadar
|
38
|
+
|
39
|
+
# Udate (we made error - mistakenly set Tassadar's attack as zero, let's fix it).
|
40
|
+
tassadar[:stats][:attack] = 20
|
41
|
+
db.units.save tassadar
|
42
|
+
|
43
|
+
# Querying first & all, there's also :each, the same as :all.
|
44
|
+
db.units.first name: 'Zeratul' # => zeratul
|
45
|
+
db.units.all name: 'Zeratul' # => [zeratul]
|
46
|
+
db.units.all name: 'Zeratul' do |unit|
|
47
|
+
unit # => zeratul
|
48
|
+
end
|
49
|
+
|
50
|
+
# Dynamic Finders (bang versions also availiable).
|
51
|
+
db.units.by_name 'Zeratul' # => zeratul
|
52
|
+
db.units.first_by_name 'Zeratul' # => zeratul
|
53
|
+
db.units.all_by_name 'Zeratul' # => [zeratul]
|
54
|
+
|
55
|
+
# Query sugar, use {name: {_gt: 'Z'}} instead of {name: {:$gt => 'Z'}}.
|
56
|
+
Mongo.defaults.merge! convert_underscore_to_dollar: true
|
57
|
+
db.units.all name: {_gt: 'Z'} # => [zeratul]
|
58
|
+
```
|
59
|
+
|
60
|
+
Source: examples/driver.rb
|
61
|
+
|
62
|
+
More docs - there's no need for more docs, the whole point of this extension is to be small, intuitive, 100% compatible with the official driver, and require no extra knowledge.
|
63
|
+
So, please use standard Ruby driver documentation.
|
64
|
+
|
65
|
+
# Persistence for any Ruby object
|
66
|
+
|
67
|
+
Save any Ruby object to MongoDB, as if it's a document. Objects can be any type, simple or composite with other objects / arrays / hashes inside.
|
68
|
+
|
69
|
+
Note: the :initialize method should allow to create object without arguments.
|
70
|
+
|
71
|
+
``` ruby
|
72
|
+
# Let's define the game unit.
|
73
|
+
class Unit
|
74
|
+
attr_reader :name, :stats
|
75
|
+
|
76
|
+
# don't forget to allow creating object with no arguments
|
77
|
+
def initialize name = nil, stats = nil
|
78
|
+
@name, @stats = name, stats
|
79
|
+
end
|
80
|
+
|
81
|
+
class Stats
|
82
|
+
attr_accessor :attack, :life, :shield
|
83
|
+
|
84
|
+
def initialize attack = nil, life = nil, shield = nil
|
85
|
+
@attack, @life, @shield = attack, life, shield
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Connecting to MongoDB.
|
91
|
+
require 'mongodb/object'
|
92
|
+
Mongo.defaults.merge! symbolize: true, multi: true, safe: true
|
93
|
+
connection = Mongo::Connection.new
|
94
|
+
db = connection.db 'default_test'
|
95
|
+
db.units.drop
|
96
|
+
|
97
|
+
# Create.
|
98
|
+
zeratul = Unit.new('Zeratul', Unit::Stats.new(85, 300, 100))
|
99
|
+
tassadar = Unit.new('Tassadar', Unit::Stats.new(0, 80, 300))
|
100
|
+
|
101
|
+
db.units.save zeratul
|
102
|
+
db.units.save tassadar
|
103
|
+
|
104
|
+
# Udate (we made error - mistakenly set Tassadar's attack as zero, let's fix it).
|
105
|
+
tassadar.stats.attack = 20
|
106
|
+
db.units.save tassadar
|
107
|
+
|
108
|
+
# Querying first & all, there's also :each, the same as :all.
|
109
|
+
db.units.first name: 'Zeratul' # => zeratul
|
110
|
+
db.units.all name: 'Zeratul' # => [zeratul]
|
111
|
+
db.units.all name: 'Zeratul' do |unit|
|
112
|
+
unit # => zeratul
|
113
|
+
end
|
114
|
+
|
115
|
+
# Simple finders (bang versions also availiable).
|
116
|
+
db.units.by_name 'Zeratul' # => zeratul
|
117
|
+
db.units.first_by_name 'Zeratul' # => zeratul
|
118
|
+
db.units.all_by_name 'Zeratul' # => [zeratul]
|
119
|
+
|
120
|
+
# Query sugar, use {name: {_gt: 'Z'}} instead of {name: {:$gt => 'Z'}}.
|
121
|
+
Mongo.defaults.merge! convert_underscore_to_dollar: true
|
122
|
+
db.units.all name: {_gt: 'Z'} # => [zeratul]
|
123
|
+
```
|
124
|
+
|
125
|
+
Source: examples/object.rb
|
126
|
+
|
127
|
+
# Object Model
|
128
|
+
|
129
|
+
- The same API for pure driver and Models.
|
130
|
+
- Minimum extra abstractions, trying to keep things as close to the MongoDB semantic as possible.
|
131
|
+
- Schema-less, dynamic (with ability to specify types for mass-assignment).
|
7
132
|
- Models can be saved to any collection.
|
8
|
-
- Full support for embedded objects (
|
9
|
-
-
|
133
|
+
- Full support for embedded objects (validations, callbacks, ...).
|
134
|
+
- Scope, default_scope
|
135
|
+
- Doesn't try to mimic ActiveRecord, MongoDB is differrent and this tool designed to get most of it.
|
136
|
+
- Very small, see [code stats][code_stats].
|
137
|
+
|
138
|
+
Other ODM usually try to cover simple but non-standard API of MongoDB behind complex ORM-like abstractions. This tool **exposes simplicity and power of MongoDB and leverages it's differences**.
|
139
|
+
|
140
|
+
``` ruby
|
141
|
+
# Connecting to MongoDB.
|
142
|
+
require 'mongodb/model'
|
143
|
+
Mongo.defaults.merge! symbolize: true, multi: true, safe: true
|
144
|
+
connection = Mongo::Connection.new
|
145
|
+
db = connection.db 'default_test'
|
146
|
+
db.units.drop
|
147
|
+
Mongo::Model.db = db
|
148
|
+
|
149
|
+
# Let's define the game unit.
|
150
|
+
class Unit
|
151
|
+
inherit Mongo::Model
|
152
|
+
collection :units
|
153
|
+
|
154
|
+
attr_accessor :name, :status, :stats
|
155
|
+
|
156
|
+
scope :alive, status: 'alive'
|
157
|
+
|
158
|
+
class Stats
|
159
|
+
inherit Mongo::Model
|
160
|
+
attr_accessor :attack, :life, :shield
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Create.
|
165
|
+
zeratul = Unit.build(name: 'Zeratul', status: 'alive', stats: Unit::Stats.build(attack: 85, life: 300, shield: 100))
|
166
|
+
tassadar = Unit.build(name: 'Tassadar', status: 'dead', stats: Unit::Stats.build(attack: 0, life: 80, shield: 300))
|
167
|
+
|
168
|
+
zeratul.save
|
169
|
+
tassadar.save
|
170
|
+
|
171
|
+
# Udate (we made error - mistakenly set Tassadar's attack as zero, let's fix it).
|
172
|
+
tassadar.stats.attack = 20
|
173
|
+
tassadar.save
|
174
|
+
|
175
|
+
# Querying first & all, there's also :each, the same as :all.
|
176
|
+
Unit.first name: 'Zeratul' # => zeratul
|
177
|
+
Unit.all name: 'Zeratul' # => [zeratul]
|
178
|
+
Unit.all name: 'Zeratul' do |unit|
|
179
|
+
unit # => zeratul
|
180
|
+
end
|
181
|
+
|
182
|
+
# Simple finders (bang versions also availiable).
|
183
|
+
Unit.by_name 'Zeratul' # => zeratul
|
184
|
+
Unit.first_by_name 'Zeratul' # => zeratul
|
185
|
+
Unit.all_by_name 'Zeratul' # => [zeratul]
|
186
|
+
|
187
|
+
# Scopes.
|
188
|
+
Unit.alive.count # => 1
|
189
|
+
Unit.alive.first # => zeratul
|
190
|
+
|
191
|
+
# Callbacks & callbacks on embedded models.
|
192
|
+
|
193
|
+
# Validations.
|
194
|
+
|
195
|
+
# Save model to any collection.
|
196
|
+
```
|
197
|
+
|
198
|
+
Source: examples/model.rb
|
199
|
+
|
200
|
+
# Migrations
|
201
|
+
|
202
|
+
Define migration steps, specify desired version and apply it (usually all this should be done via Rake task).
|
203
|
+
|
204
|
+
``` ruby
|
205
|
+
require 'mongodb/migration'
|
206
|
+
|
207
|
+
# Connection & db.
|
208
|
+
connection = Mongo::Connection.new
|
209
|
+
db = connection.db 'default_test'
|
210
|
+
db.units.drop
|
211
|
+
|
212
|
+
# Initialize migration (usually all this should be done inside of :migrate
|
213
|
+
# rake task).
|
214
|
+
migration = Mongo::Migration.new db
|
215
|
+
|
216
|
+
# Define migrations.
|
217
|
+
# Usually they are defined as files in some folder and You loading it by
|
218
|
+
# using something like this:
|
219
|
+
# Dir['<runtime_dir>/db/migrations/*.rb'].each{|fname| load fname}
|
220
|
+
migration.add 1 do |m|
|
221
|
+
m.up{|db| db.units.save name: 'Zeratul'}
|
222
|
+
m.down{|db| db.units.remove name: 'Zeratul'}
|
223
|
+
end
|
224
|
+
|
225
|
+
# Let's add another one.
|
226
|
+
migration.add 2 do |m|
|
227
|
+
m.up{|db| db.units.save name: 'Tassadar'}
|
228
|
+
m.down{|db| db.units.remove name: 'Tassadar'}
|
229
|
+
end
|
230
|
+
|
231
|
+
# Specify what version of database You need and apply migration.
|
232
|
+
migration.update 2
|
233
|
+
|
234
|
+
migration.current_version # => 2
|
235
|
+
db.units.count # => 2
|
236
|
+
|
237
|
+
# You can rollback it the same way.
|
238
|
+
migration.update 0
|
239
|
+
|
240
|
+
migration.current_version # => 0
|
241
|
+
db.units.count # => 0
|
242
|
+
|
243
|
+
# To update to the highest version just call it without the version specified
|
244
|
+
migration.update
|
245
|
+
|
246
|
+
migration.current_version # => 2
|
247
|
+
db.units.count # => 2
|
248
|
+
```
|
249
|
+
|
250
|
+
Source: examples/migration.rb
|
251
|
+
|
252
|
+
# Installation
|
253
|
+
|
254
|
+
``` bash
|
255
|
+
gem install mongodb
|
256
|
+
```
|
257
|
+
|
258
|
+
# License
|
259
|
+
|
260
|
+
Copyright (c) Alexey Petrushin, http://petrush.in, released under the MIT license.
|
261
|
+
|
262
|
+
[mongo_mapper_ext]: https://github.com/alexeypetrushin/mongo_mapper_ext
|
263
|
+
[mongoid_misc]: https://github.com/alexeypetrushin/mongoid_misc
|
264
|
+
[code_stats]: https://github.com/alexeypetrushin/mongodb/raw/master/docs/code_stats.png
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'driver/spec_helper'
|
2
|
+
|
3
|
+
describe "Collection" do
|
4
|
+
with_mongo
|
5
|
+
|
6
|
+
it 'by default save must update all matched by criteria (not first as defautl in mongo)' do
|
7
|
+
db.units.save name: 'Probe', race: 'Protoss', status: 'alive'
|
8
|
+
db.units.save name: 'Zealot', race: 'Protoss', status: 'alive'
|
9
|
+
|
10
|
+
# update
|
11
|
+
db.units.update({race: 'Protoss'}, :$set => {status: 'dead'})
|
12
|
+
db.units.all.collect{|u| u[:status]}.should == %w(dead dead)
|
13
|
+
|
14
|
+
# destroy
|
15
|
+
db.units.destroy race: 'Protoss'
|
16
|
+
db.units.count.should == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "symbolize" do
|
20
|
+
it 'should always return symbolized hashes' do
|
21
|
+
zeratul = {name: 'Zeratul'}
|
22
|
+
db.units.save(zeratul).should be_mongo_id
|
23
|
+
r = db.units.first(name: 'Zeratul')
|
24
|
+
r[:_id].should be_mongo_id
|
25
|
+
r['_id'].should be_nil
|
26
|
+
r[:name].should == 'Zeratul'
|
27
|
+
r['name'].should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be able to disable symbolization" do
|
31
|
+
old = Mongo.defaults[:symbolize]
|
32
|
+
begin
|
33
|
+
Mongo.defaults[:symbolize] = false
|
34
|
+
|
35
|
+
zeratul = {name: 'Zeratul'}
|
36
|
+
db.units.save(zeratul).should be_mongo_id
|
37
|
+
r = db.units.first(name: 'Zeratul')
|
38
|
+
r[:_id].should be_nil
|
39
|
+
r['_id'].should be_mongo_id
|
40
|
+
r[:name].should be_nil
|
41
|
+
r['name'].should == 'Zeratul'
|
42
|
+
ensure
|
43
|
+
Mongo.defaults[:symbolize] = old
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "first" do
|
49
|
+
db.units.first.should be_nil
|
50
|
+
zeratul = {name: 'Zeratul'}
|
51
|
+
db.units.save(zeratul).should be_mongo_id
|
52
|
+
db.units.first(name: 'Zeratul')[:name].should == 'Zeratul'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'all' do
|
56
|
+
db.units.all.should == []
|
57
|
+
|
58
|
+
zeratul = {name: 'Zeratul'}
|
59
|
+
db.units.save(zeratul).should be_mongo_id
|
60
|
+
|
61
|
+
list = db.units.all(name: 'Zeratul')
|
62
|
+
list.size.should == 1
|
63
|
+
list.first[:name].should == 'Zeratul'
|
64
|
+
|
65
|
+
# with block
|
66
|
+
list = []; db.units.all{|o| list << o}
|
67
|
+
list.size.should == 1
|
68
|
+
list.first[:name].should == 'Zeratul'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'count' do
|
72
|
+
db.units.count(name: 'Zeratul').should == 0
|
73
|
+
db.units.save name: 'Zeratul'
|
74
|
+
db.units.save name: 'Tassadar'
|
75
|
+
db.units.count(name: 'Zeratul').should == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
it "underscore to dollar" do
|
79
|
+
db.units.save name: 'Jim', age: 34
|
80
|
+
db.units.save name: 'Zeratul', age: 600
|
81
|
+
db.units.all(age: {_lt: 100}).count.should == 1
|
82
|
+
end
|
83
|
+
end
|
@@ -1,53 +1,54 @@
|
|
1
|
-
require 'spec_helper'
|
1
|
+
require 'driver/spec_helper'
|
2
2
|
|
3
3
|
describe "Hash CRUD" do
|
4
|
-
|
5
|
-
|
4
|
+
with_mongo
|
5
|
+
|
6
6
|
describe 'simple' do
|
7
7
|
before do
|
8
8
|
@zeratul = {name: 'Zeratul', info: 'Dark Templar'}
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it 'crud' do
|
12
12
|
# read
|
13
|
-
db.
|
14
|
-
db.
|
15
|
-
db.
|
16
|
-
|
13
|
+
db.units.count.should == 0
|
14
|
+
db.units.all.should == []
|
15
|
+
db.units.first.should == nil
|
16
|
+
|
17
17
|
# create
|
18
|
-
db.
|
19
|
-
|
18
|
+
db.units.save(@zeratul).should be_mongo_id
|
19
|
+
@zeratul[:_id].should be_mongo_id
|
20
|
+
|
20
21
|
# read
|
21
|
-
db.
|
22
|
-
db.
|
23
|
-
db.
|
24
|
-
|
22
|
+
db.units.all.should == [@zeratul]
|
23
|
+
db.units.count.should == 1
|
24
|
+
db.units.first.should == @zeratul
|
25
|
+
|
25
26
|
# update
|
26
27
|
@zeratul[:info] = 'Killer of Cerebrates'
|
27
|
-
db.
|
28
|
-
db.
|
29
|
-
db.
|
30
|
-
|
28
|
+
db.units.save @zeratul
|
29
|
+
db.units.count.should == 1
|
30
|
+
db.units.first(name: 'Zeratul')[:info].should == 'Killer of Cerebrates'
|
31
|
+
|
31
32
|
# destroy
|
32
|
-
db.
|
33
|
-
db.
|
33
|
+
db.units.destroy @zeratul
|
34
|
+
db.units.count.should == 0
|
34
35
|
end
|
35
36
|
end
|
36
|
-
|
37
|
+
|
37
38
|
describe 'embedded' do
|
38
|
-
before do
|
39
|
+
before do
|
39
40
|
@player = {
|
40
41
|
name: 'Alex',
|
41
42
|
missions: [
|
42
43
|
{name: 'Wasteland', stats: {buildings: 5, units: 10}},
|
43
44
|
{name: 'Backwater Station', stats: {buildings: 8, units: 25}}
|
44
45
|
]
|
45
|
-
}
|
46
|
+
}
|
46
47
|
end
|
47
|
-
|
48
|
+
|
48
49
|
it 'crud' do
|
49
50
|
# create
|
50
|
-
db.players.save(@player)
|
51
|
+
db.players.save(@player).should be_mongo_id
|
51
52
|
|
52
53
|
# read
|
53
54
|
db.players.count.should == 1
|
@@ -55,15 +56,15 @@ describe "Hash CRUD" do
|
|
55
56
|
|
56
57
|
# update
|
57
58
|
@player[:missions].first[:stats][:units] = 9
|
58
|
-
@player.
|
59
|
-
db.players.save(
|
59
|
+
@player[:missions].push name: 'Desperate Alliance', stats: {buildings: 11, units: 40}
|
60
|
+
db.players.save(@player).should_not be_nil
|
60
61
|
db.players.count.should == 1
|
61
62
|
db.players.first.should == @player
|
62
63
|
db.players.first.object_id.should_not == @player.object_id
|
63
64
|
|
64
65
|
# destroy
|
65
|
-
db.players.destroy
|
66
|
+
db.players.destroy @player
|
66
67
|
db.players.count.should == 0
|
67
68
|
end
|
68
|
-
end
|
69
|
+
end
|
69
70
|
end
|