mongoo 0.1.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.
@@ -0,0 +1,91 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{mongoo}
8
+ s.version = "0.1.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ben Myles"]
12
+ s.date = %q{2011-02-15}
13
+ s.description = %q{Simple object mapper for MongoDB}
14
+ s.email = %q{ben.myles@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rvmrc",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/mongoo.rb",
28
+ "lib/mongoo/attribute_proxy.rb",
29
+ "lib/mongoo/attribute_sanitizer.rb",
30
+ "lib/mongoo/base.rb",
31
+ "lib/mongoo/changelog.rb",
32
+ "lib/mongoo/cursor.rb",
33
+ "lib/mongoo/hash_ext.rb",
34
+ "lib/mongoo/modifiers.rb",
35
+ "lib/mongoo/mongohash.rb",
36
+ "lib/mongoo/persistence.rb",
37
+ "test/helper.rb",
38
+ "test/test_activemodel.rb",
39
+ "test/test_mongohash.rb",
40
+ "test/test_mongoo.rb"
41
+ ]
42
+ s.homepage = %q{http://github.com/benmyles/mongoo}
43
+ s.licenses = ["MIT"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.7}
46
+ s.summary = %q{Object mapper for MongoDB}
47
+ s.test_files = [
48
+ "test/helper.rb",
49
+ "test/test_activemodel.rb",
50
+ "test/test_mongohash.rb",
51
+ "test/test_mongoo.rb"
52
+ ]
53
+
54
+ if s.respond_to? :specification_version then
55
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
+ s.specification_version = 3
57
+
58
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
59
+ s.add_runtime_dependency(%q<i18n>, [">= 0.4.1"])
60
+ s.add_runtime_dependency(%q<activesupport>, [">= 3.0.3"])
61
+ s.add_runtime_dependency(%q<activemodel>, [">= 3.0.3"])
62
+ s.add_runtime_dependency(%q<mongo-em>, [">= 1.2.1"])
63
+ s.add_runtime_dependency(%q<bson_ext>, [">= 1.2.2"])
64
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
65
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
66
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
67
+ s.add_development_dependency(%q<rcov>, [">= 0"])
68
+ else
69
+ s.add_dependency(%q<i18n>, [">= 0.4.1"])
70
+ s.add_dependency(%q<activesupport>, [">= 3.0.3"])
71
+ s.add_dependency(%q<activemodel>, [">= 3.0.3"])
72
+ s.add_dependency(%q<mongo-em>, [">= 1.2.1"])
73
+ s.add_dependency(%q<bson_ext>, [">= 1.2.2"])
74
+ s.add_dependency(%q<shoulda>, [">= 0"])
75
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
76
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
77
+ s.add_dependency(%q<rcov>, [">= 0"])
78
+ end
79
+ else
80
+ s.add_dependency(%q<i18n>, [">= 0.4.1"])
81
+ s.add_dependency(%q<activesupport>, [">= 3.0.3"])
82
+ s.add_dependency(%q<activemodel>, [">= 3.0.3"])
83
+ s.add_dependency(%q<mongo-em>, [">= 1.2.1"])
84
+ s.add_dependency(%q<bson_ext>, [">= 1.2.2"])
85
+ s.add_dependency(%q<shoulda>, [">= 0"])
86
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
87
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
88
+ s.add_dependency(%q<rcov>, [">= 0"])
89
+ end
90
+ end
91
+
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ groups = [:default, :development]
5
+ if defined?(EM) && EM.reactor_running?
6
+ groups << :async
7
+ else
8
+ groups << :sync
9
+ end
10
+ Bundler.setup(groups)
11
+ rescue Bundler::BundlerError => e
12
+ $stderr.puts e.message
13
+ $stderr.puts "Run `bundle install` to install missing gems"
14
+ exit e.status_code
15
+ end
16
+ require 'test/unit'
17
+ require 'shoulda'
18
+
19
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
20
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
21
+ require 'mongoo'
22
+
23
+ Mongoo.config = {host: "127.0.0.1", port: 27017, db: 'mongoo-test'}
24
+
25
+ class SearchIndex < Mongoo::Base
26
+ attribute "terms", :type => :array
27
+ index "terms"
28
+ end
29
+
30
+ class Person < Mongoo::Base
31
+ attribute "name", :type => :string
32
+ attribute "visits", :type => :integer
33
+ attribute "interests", :type => :array
34
+ attribute "jobs.total", :type => :integer
35
+ attribute "jobs.professional", :type => :array
36
+ attribute "jobs.volunteer", :type => :array
37
+ attribute "jobs.internships.high_school", :type => :array
38
+ attribute "location.city", :type => :string
39
+ attribute "location.demographics.crime_rate", :type => :symbol
40
+ attribute "location.demographics.education_quality", :type => :symbol
41
+ attribute "misc", :type => :hash
42
+
43
+ index "name"
44
+ index "location.city"
45
+ end
46
+
47
+ class TvShow < Mongoo::Base
48
+ attribute "name", :type => :string
49
+ attribute "cast.director", :type => :string
50
+ attribute "cast.lead", :type => :string
51
+ attribute "rating", :type => :float
52
+ attribute "comments", :type => :array
53
+
54
+ index "name"
55
+
56
+ validates_presence_of "name"
57
+ validates_presence_of "cast.director"
58
+ validates_presence_of "rating"
59
+ end
60
+
61
+ class Test::Unit::TestCase
62
+ end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+
3
+ class TestActivemodel < Test::Unit::TestCase
4
+ include ActiveModel::Lint::Tests
5
+
6
+ def setup
7
+ [TvShow].each do |obj|
8
+ obj.drop
9
+ obj.create_indexes
10
+ end
11
+ @model = TvShow.new
12
+ end
13
+ end
14
+
@@ -0,0 +1,36 @@
1
+ require 'helper'
2
+
3
+ class TestMongohash < Test::Unit::TestCase
4
+ should "work with dot_get, dot_set, dot_delete" do
5
+ h = Mongoo::Mongohash.new({
6
+ "name" => "Ben",
7
+ "travel" => {},
8
+ "location" => { "city" => "SF", "zip" => 94107, "demographics" => { "pop" => 120000 } }})
9
+ assert_equal "Ben", h.dot_get("name")
10
+ assert_equal "SF", h.dot_get("location.city")
11
+ assert_equal 94107, h.dot_get("location.zip")
12
+ assert_equal 120000, h.dot_get("location.demographics.pop")
13
+ assert_equal nil, h.dot_get("foobar")
14
+ assert_equal nil, h.dot_get("location.idontexist.andneitherdoi")
15
+ h.dot_set("location.demographics.pop", 10000)
16
+ assert_equal 10000, h.dot_get("location.demographics.pop")
17
+ h.dot_set("interests", ["skydiving"])
18
+ assert_equal ["skydiving"], h.dot_get("interests")
19
+ h.dot_set("languages.fluent", ["english"])
20
+ h.dot_set("languages.nonfluent", ["german"])
21
+ assert_equal ["english"], h.dot_get("languages.fluent")
22
+ assert_equal ["german"], h.dot_get("languages.nonfluent")
23
+ h.dot_delete("languages.fluent")
24
+ assert_equal nil, h.dot_get("languages.fluent")
25
+ h.dot_delete("languages")
26
+ assert_equal nil, h.dot_get("languages")
27
+ assert_equal "Ben", h.dot_get("name")
28
+ h.dot_delete("name")
29
+ assert_equal nil, h.dot_get("name")
30
+ end
31
+
32
+ # should "not be able to initialize an object with undefined attributes" do
33
+ # assert_raise(Mongoo::UnknownAttributeError) { Person.new(:idontexist => "bah") }
34
+ # end
35
+ end
36
+
@@ -0,0 +1,276 @@
1
+ require 'helper'
2
+
3
+ class TestMongoo < Test::Unit::TestCase
4
+
5
+ def setup
6
+ [Person, TvShow, SearchIndex].each do |obj|
7
+ obj.drop
8
+ obj.create_indexes
9
+ end
10
+ end
11
+
12
+ should "set and get attributes" do
13
+ p = Person.new("name" => "Ben")
14
+ assert_equal "Ben", p.g(:name)
15
+ assert_equal "Ben", p.get(:name)
16
+ assert_equal "Ben", p.get_attribute(:name)
17
+ p.set("location.city", "San Francisco")
18
+ assert_equal "San Francisco", p.get("location.city")
19
+ p.sets({"location.demographics.crime_rate" => :high, "location.demographics.education_quality" => :low})
20
+ assert_equal({"name"=>"Ben",
21
+ "location.demographics.crime_rate"=>:high}, p.gets(%w(name location.demographics.crime_rate)))
22
+ assert_raise(Mongoo::UnknownAttributeError) { p.set("idontexist", "foo") }
23
+ assert_raise(Mongoo::UnknownAttributeError) { p.get("idontexist") }
24
+ assert_raise(NoMethodError) { p.idontexist }
25
+ assert_raise(NoMethodError) { p.idontexist = "val" }
26
+ end
27
+
28
+ should "have attribute methods" do
29
+ p = Person.new("name" => "Ben", "jobs" => { "professional" => "iList" })
30
+ p.jobs.internships.high_school = ["Sun Microsystems"]
31
+ assert_equal ["Sun Microsystems"], p.jobs.internships.high_school
32
+ assert_equal ["Sun Microsystems"], p.get("jobs.internships.high_school")
33
+ p.name = "Ben Myles"
34
+ assert_equal "Ben Myles", p.name
35
+ assert_equal "Ben Myles", p.get("name")
36
+ end
37
+
38
+ should "never has the same object for persisted_mongohash and mongohash" do
39
+ p = Person.new("name" => "Ben")
40
+ p.insert
41
+ p.name = "Ben Myles"
42
+ assert_not_equal p.persisted_mongohash.raw_hash, p.mongohash.raw_hash
43
+ p.update
44
+ assert_equal p.persisted_mongohash.raw_hash, p.mongohash.raw_hash
45
+ p.name = "Ben 2"
46
+ assert_not_equal p.persisted_mongohash.raw_hash, p.mongohash.raw_hash
47
+ end
48
+
49
+ should "be able to do crud" do
50
+ p = Person.new("name" => "Ben")
51
+ p.jobs.internships.high_school = ["Sun Microsystems"]
52
+ p.insert
53
+
54
+ p = Person.find_one(p.id)
55
+ p.update
56
+ p.location.city = "San Francisco"
57
+ p.update
58
+ p.name = "Ben Myles"
59
+ p.location.city = "San Diego"
60
+ assert_not_equal p.persisted_mongohash.raw_hash, p.mongohash.raw_hash
61
+ p.update
62
+
63
+ p2 = Person.find_one(p.id)
64
+ assert_equal "Ben Myles", p2.name
65
+ assert_equal "San Diego", p2.location.city
66
+
67
+ p.location.city = "Los Angeles"
68
+ p.update!
69
+
70
+ p2.location.city = "San Jose"
71
+ assert_raise(Mongoo::StaleUpdateError) { p2.update! }
72
+ p2.location.city = "San Diego"
73
+ p2.name = "Benjamin"
74
+ p2.update!
75
+
76
+ assert p2.reload
77
+
78
+ assert_equal "Los Angeles", p2.location.city
79
+ assert_equal "Benjamin", p2.name
80
+
81
+ assert p2.persisted_mongohash.raw_hash["location"].has_key?("city")
82
+ p2.unset "location.city"
83
+ p2.update
84
+ assert !p2.persisted_mongohash.raw_hash["location"].has_key?("city")
85
+
86
+ p2.location.demographics.crime_rate = :high
87
+ p2.location.city = "San Bruno"
88
+ p2.update
89
+ assert_raise(NoMethodError) { p2.location.demographics = 123 }
90
+
91
+ p2.unset "location"
92
+ p2.update
93
+ p2 = Person.find_one(p2.id)
94
+ assert !p2.persisted_mongohash.raw_hash.has_key?("location")
95
+
96
+ p2.location.city = "Brisbane"
97
+ p2.location.demographics.crime_rate = :low
98
+ p2.update
99
+ assert_equal ["Brisbane", :low], [p2.location.city, p2.location.demographics.crime_rate]
100
+ p2 = Person.find_one(p2.id)
101
+ assert_equal ["Brisbane", :low], [p2.location.city, p2.location.demographics.crime_rate]
102
+ p2.location.unset
103
+ p2.update
104
+ assert !p2.persisted_mongohash.raw_hash.has_key?("location")
105
+ p2 = Person.find_one(p2.id)
106
+ assert !p2.persisted_mongohash.raw_hash.has_key?("location")
107
+
108
+ p2.location.city = "Brisbane"
109
+ p2.location.demographics.crime_rate = :low
110
+ p2.update
111
+ assert_equal ["Brisbane", :low], [p2.location.city, p2.location.demographics.crime_rate]
112
+ assert p2.persisted_mongohash.raw_hash["location"].has_key?("demographics")
113
+ p2.location.demographics.unset
114
+ p2.update
115
+ assert !p2.persisted_mongohash.raw_hash["location"].has_key?("demographics")
116
+ p2 = Person.find_one(p2.id)
117
+ assert !p2.persisted_mongohash.raw_hash["location"].has_key?("demographics")
118
+ assert_equal "Brisbane", p2.location.city
119
+ end
120
+
121
+ should "be able to modify fields" do
122
+ p = Person.new("name" => "Ben", "visits" => 0)
123
+ p.insert!
124
+ assert_equal 0, p.visits
125
+
126
+ p.mod! do |mod|
127
+ mod.inc "visits", 2
128
+ mod.set "jobs.total", 10
129
+ end
130
+ assert_equal 2, p.visits
131
+ assert_equal 10, p.jobs.total
132
+ assert_equal [], p.changelog
133
+ p = Person.find_one(p.id)
134
+ assert_equal 2, p.visits
135
+ assert_equal 10, p.jobs.total
136
+
137
+ p.jobs.mod! do |mod|
138
+ mod.inc "total", 5
139
+ end
140
+ assert_equal 15, p.jobs.total
141
+ p = Person.find_one(p.id)
142
+ assert_equal 15, p.jobs.total
143
+
144
+ assert_equal nil, p.interests
145
+ p.mod! { |mod| mod.push("interests", "skydiving") }
146
+ assert_equal ["skydiving"], p.interests
147
+ p = Person.find_one(p.id)
148
+ assert_equal ["skydiving"], p.interests
149
+ p.mod! { |mod| mod.push("interests", "snowboarding") }
150
+ assert_equal ["skydiving", "snowboarding"], p.interests
151
+ p = Person.find_one(p.id)
152
+ assert_equal ["skydiving", "snowboarding"], p.interests
153
+
154
+ p.mod! { |mod| mod.push_all("interests", ["reading","travelling"]) }
155
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling"], p.interests
156
+ p = Person.find_one(p.id)
157
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling"], p.interests
158
+
159
+ p.mod! { |mod| mod.add_to_set("interests", "skydiving") }
160
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling"], p.interests
161
+ p.mod! { |mod| mod.add_to_set("interests", "swimming") }
162
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling", "swimming"], p.interests
163
+ p.mod! { |mod| mod.add_to_set("interests", "swimming") }
164
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling", "swimming"], p.interests
165
+
166
+ p.mod! { |mod| mod.pop("interests") }
167
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling"], p.interests
168
+
169
+ p.mod! { |mod| mod.pop("interests") }
170
+ assert_equal ["skydiving", "snowboarding", "reading"], p.interests
171
+
172
+ p.mod! { |mod| mod.push("interests", "reading") }
173
+ assert_equal ["skydiving", "snowboarding", "reading", "reading"], p.interests
174
+ p = Person.find_one(p.id)
175
+ assert_equal ["skydiving", "snowboarding", "reading", "reading"], p.interests
176
+ p.mod! { |mod| mod.pull("interests", "reading") }
177
+ assert_equal ["skydiving", "snowboarding"], p.interests
178
+ p = Person.find_one(p.id)
179
+ assert_equal ["skydiving", "snowboarding"], p.interests
180
+
181
+ p.mod! { |mod| mod.push_all("interests", ["reading","travelling"]) }
182
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling"], p.interests
183
+ p = Person.find_one(p.id)
184
+ assert_equal ["skydiving", "snowboarding", "reading", "travelling"], p.interests
185
+
186
+ p.mod! { |mod| mod.pull_all("interests", ["reading", "skydiving"]) }
187
+ assert_equal ["snowboarding", "travelling"], p.interests
188
+ p = Person.find_one(p.id)
189
+ assert_equal ["snowboarding", "travelling"], p.interests
190
+ end
191
+
192
+ should "not be able to modify fields that don't exist" do
193
+ p = Person.new("name" => "Ben", "visits" => 0)
194
+ p.insert!
195
+ assert_raise(Mongoo::UnknownAttributeError) do
196
+ p.mod! { |mod| mod.push("idontexist", "foobar") }
197
+ end
198
+ end
199
+
200
+ should "be able to access a hash type directly" do
201
+ p = Person.new("name" => "Ben")
202
+ p.insert!
203
+ assert_equal nil, p.misc
204
+ p.misc = { "height" => 5.5, "weight" => 160 }
205
+ p.update!
206
+ assert_equal({ "height" => 5.5, "weight" => 160 }, p.misc)
207
+ p.update!
208
+ p = Person.find_one(p.id)
209
+ assert_equal({ "height" => 5.5, "weight" => 160 }, p.misc)
210
+ p.misc["height"] = 5.6
211
+ p.misc["eyes"] = :blue
212
+ assert_equal({ "height" => 5.6, "weight" => 160, "eyes" => :blue }, p.misc)
213
+ p.update!
214
+ assert_equal({ "height" => 5.6, "weight" => 160, "eyes" => :blue }, p.misc)
215
+ p = Person.find_one(p.id)
216
+ assert_equal({ "height" => 5.6, "weight" => 160, "eyes" => :blue }, p.misc)
217
+ end
218
+
219
+ should "cast to type automatically" do
220
+ p = Person.new("name" => "ben")
221
+ p.insert!
222
+ p.visits = "5"
223
+ assert_equal 5, p.visits
224
+ p.update!
225
+ p = Person.find_one(p.id)
226
+ assert_equal 5, p.visits
227
+ p.mod! { |mod| mod.inc("visits", 3) }
228
+ assert_equal 8, p.visits
229
+ p = Person.find_one(p.id)
230
+ assert_equal 8, p.visits
231
+ end
232
+
233
+ should "validate documents" do
234
+ show = TvShow.new
235
+ assert !show.valid?
236
+ assert !show.insert
237
+ assert_equal({:name=>["can't be blank"],
238
+ :"cast.director"=>["can't be blank"],
239
+ :rating=>["can't be blank"]}, show.errors)
240
+ show.cast.director = "Some Guy"
241
+ show.name = "Some Show"
242
+ assert !show.valid?
243
+ assert !show.insert
244
+ assert_raise(Mongoo::NotValidError) { show.insert! }
245
+ assert_equal({:rating=>["can't be blank"]}, show.errors)
246
+ show.rating = 3.0
247
+ assert show.valid?
248
+ show.insert!
249
+ end
250
+
251
+ should "not care if keys are symbols or hashes" do
252
+ p = Person.new(:name => "Ben")
253
+ assert_equal "Ben", p.name
254
+ end
255
+
256
+ should "be able to merge properties into the mongohash" do
257
+ p = Person.new("name" => "Ben", "visits" => 10, "location" => { "city" => "SF" })
258
+ p.insert!
259
+ p = Person.find_one(p.id)
260
+ assert_equal "Ben", p.name
261
+ assert_equal 10, p.visits
262
+ assert_equal "SF", p.location.city
263
+ p.merge!({"visits" => 12, "location" => { "demographics" => {"crime_rate" => :high} } })
264
+ assert_equal "Ben", p.name
265
+ assert_equal 12, p.visits
266
+ assert_equal "SF", p.location.city
267
+ end
268
+
269
+ should "not fail on an empty array" do
270
+ i = SearchIndex.new(:terms => [])
271
+ i.insert!
272
+ i.terms << "foo"
273
+ i.update!
274
+ end
275
+ end
276
+