candy 0.2.1 → 0.2.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/HISTORY.markdown +8 -0
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/candy.gemspec +11 -5
- data/lib/candy/crunch.rb +77 -4
- data/lib/candy/wrapper.rb +5 -12
- data/spec/candy/crunch_spec.rb +37 -2
- data/spec/candy/piece_spec.rb +2 -2
- data/spec/candy/wrapper_spec.rb +3 -3
- metadata +38 -10
data/HISTORY.markdown
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
This document aims to provide only an overview. Further, we've only really been tracking things since **v0.2**. For obsessive detail, just check out the `git log`.
|
4
4
|
|
5
|
+
## v0.2.2 - 2010-04-12 (the "I hate reporting bugs to the MongoDB team" release)
|
6
|
+
|
7
|
+
The Mongo gem has broken the BSON functions out into a separate bson gem, so I had to fix things. This means Candy is no longer compatible with the Mongo gem < 0.20.1. Que sera. (Also, the bson_ext gem **must** be installed due to a bug. I'll remove the dependency when they fix it.) Additional minor bonus: authentication.
|
8
|
+
|
9
|
+
* New BSON::* classes correctly referenced in Candy::Wrapper
|
10
|
+
* Candy.username and Candy.password properties to automatically authenticate at the global level
|
11
|
+
* Class-specific .username and .password properties for class-specific databases
|
12
|
+
|
5
13
|
## v0.2.1 - 2010-04-04 (the "Oops" release)
|
6
14
|
|
7
15
|
I screwed up in my use of Jeweler, and managed to get my versions out of sync between Github and Rubygems.org. I tried to `gem yank` the one from Rubygems, but it won't let me push again with the same version number. To justify bumping the patch number, I added this changelog. Yeah, I know. Pathetic.
|
data/Rakefile
CHANGED
@@ -16,7 +16,9 @@ DESCRIPTION
|
|
16
16
|
gem.email = "sfeley@gmail.com"
|
17
17
|
gem.homepage = "http://github.com/SFEley/candy"
|
18
18
|
gem.authors = ["Stephen Eley"]
|
19
|
-
gem.add_dependency "
|
19
|
+
gem.add_dependency "bson", ">= 0.20.1"
|
20
|
+
gem.add_dependency "bson_ext", '>= 0.20.1'
|
21
|
+
gem.add_dependency "mongo", ">= 0.20.1"
|
20
22
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
21
23
|
# gem.add_development_dependency "yard", ">= 0"
|
22
24
|
gem.add_development_dependency "mocha", ">= 0.9.8"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/candy.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{candy}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Stephen Eley"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-12}
|
13
13
|
s.description = %q{Candy provides simple, transparent object persistence for the MongoDB database. Classes that
|
14
14
|
include Candy modules save all properties to Mongo automatically, can be recursively embedded,
|
15
15
|
and can retrieve records with chainable open-ended class methods, eliminating the need for
|
@@ -76,16 +76,22 @@ method calls like 'save' and 'find.'
|
|
76
76
|
s.specification_version = 3
|
77
77
|
|
78
78
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
79
|
-
s.add_runtime_dependency(%q<
|
79
|
+
s.add_runtime_dependency(%q<bson>, [">= 0.20.1"])
|
80
|
+
s.add_runtime_dependency(%q<bson_ext>, [">= 0.20.1"])
|
81
|
+
s.add_runtime_dependency(%q<mongo>, [">= 0.20.1"])
|
80
82
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
81
83
|
s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
|
82
84
|
else
|
83
|
-
s.add_dependency(%q<
|
85
|
+
s.add_dependency(%q<bson>, [">= 0.20.1"])
|
86
|
+
s.add_dependency(%q<bson_ext>, [">= 0.20.1"])
|
87
|
+
s.add_dependency(%q<mongo>, [">= 0.20.1"])
|
84
88
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
85
89
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
86
90
|
end
|
87
91
|
else
|
88
|
-
s.add_dependency(%q<
|
92
|
+
s.add_dependency(%q<bson>, [">= 0.20.1"])
|
93
|
+
s.add_dependency(%q<bson_ext>, [">= 0.20.1"])
|
94
|
+
s.add_dependency(%q<mongo>, [">= 0.20.1"])
|
89
95
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
90
96
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
91
97
|
end
|
data/lib/candy/crunch.rb
CHANGED
@@ -58,7 +58,7 @@ module Candy
|
|
58
58
|
when Mongo::DB
|
59
59
|
@db = val
|
60
60
|
when String
|
61
|
-
@db = Mongo::DB.new(val, connection)
|
61
|
+
@db = maybe_authenticate(Mongo::DB.new(val, connection))
|
62
62
|
when nil
|
63
63
|
@db = nil
|
64
64
|
else
|
@@ -69,7 +69,29 @@ module Candy
|
|
69
69
|
# Returns the database you gave, or creates a default database named for your username (or 'candy' if it
|
70
70
|
# can't find a username).
|
71
71
|
def self.db
|
72
|
-
@db ||= Mongo::DB.new(Etc.getlogin || 'candy', connection, :strict => false)
|
72
|
+
@db ||= maybe_authenticate(Mongo::DB.new(Etc.getlogin || 'candy', connection, :strict => false))
|
73
|
+
end
|
74
|
+
|
75
|
+
# Sets the user for Mongo authentication. Both username AND password must be set or nothing will happen.
|
76
|
+
# Also ignored if you supply your own Mongo::DB object instead of a string.
|
77
|
+
def self.username=(val)
|
78
|
+
@username = val
|
79
|
+
end
|
80
|
+
|
81
|
+
# The user for Mongo authentication.
|
82
|
+
def self.username
|
83
|
+
@username
|
84
|
+
end
|
85
|
+
|
86
|
+
# Sets the password for Mongo authentication. Both username AND password must be set or nothing will happen.
|
87
|
+
# Also ignored if you supply your own Mongo::DB object instead of a string.
|
88
|
+
def self.password=(val)
|
89
|
+
@password = val
|
90
|
+
end
|
91
|
+
|
92
|
+
# The password for Mongo authentication
|
93
|
+
def self.password
|
94
|
+
@password
|
73
95
|
end
|
74
96
|
|
75
97
|
# All of the hard crunchy bits that connect us to a collection within a Mongo database.
|
@@ -97,7 +119,7 @@ module Candy
|
|
97
119
|
when Mongo::DB
|
98
120
|
@db = val
|
99
121
|
when String
|
100
|
-
@db = Mongo::DB.new(val, connection)
|
122
|
+
@db = maybe_authenticate(Mongo::DB.new(val, connection))
|
101
123
|
when nil
|
102
124
|
@db = nil
|
103
125
|
else
|
@@ -110,6 +132,30 @@ module Candy
|
|
110
132
|
@db ||= Candy.db
|
111
133
|
end
|
112
134
|
|
135
|
+
# Sets the user for Mongo authentication. Defaults to the global Candy.username.
|
136
|
+
# Both username AND password must be set or nothing will happen.
|
137
|
+
# Also ignored if you supply your own Mongo::DB object instead of a string.
|
138
|
+
def username=(val)
|
139
|
+
@username = val
|
140
|
+
end
|
141
|
+
|
142
|
+
# The user for Mongo authentication.
|
143
|
+
def username
|
144
|
+
@username ||= Candy.username
|
145
|
+
end
|
146
|
+
|
147
|
+
# Sets the password for Mongo authentication. Defaults to the global Candy.password.
|
148
|
+
# Both username AND password must be set or nothing will happen.
|
149
|
+
# Also ignored if you supply your own Mongo::DB object instead of a string.
|
150
|
+
def password=(val)
|
151
|
+
@password = val
|
152
|
+
end
|
153
|
+
|
154
|
+
# The password for Mongo authentication
|
155
|
+
def password
|
156
|
+
@password ||= Candy.password
|
157
|
+
end
|
158
|
+
|
113
159
|
# Accepts either a Mongo::Collection object or a string with the collection name. If you provide a
|
114
160
|
# Mongo::Collection object, the default database and connection are not used.
|
115
161
|
def collection=(val)
|
@@ -140,10 +186,23 @@ module Candy
|
|
140
186
|
else
|
141
187
|
raise TypeError, "Index direction should be :asc or :desc"
|
142
188
|
end
|
143
|
-
collection.create_index(property
|
189
|
+
collection.create_index([[property, mongo_direction]])
|
144
190
|
end
|
191
|
+
|
192
|
+
private
|
193
|
+
# If we don't have a username AND password, returns the DB given. If we do, returns the DB if-and-only-if
|
194
|
+
# we can authenticate on that DB.
|
195
|
+
def maybe_authenticate(db)
|
196
|
+
if @username && @password
|
197
|
+
db if db.authenticate(@username, @password)
|
198
|
+
else
|
199
|
+
db
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
145
203
|
end
|
146
204
|
|
205
|
+
|
147
206
|
# We're implementing FindAndModify on Mongo 1.4 until the Ruby driver gets around to being updated...
|
148
207
|
def findAndModify(query, update, sort={})
|
149
208
|
command = OrderedHash[
|
@@ -154,9 +213,23 @@ module Candy
|
|
154
213
|
]
|
155
214
|
result = self.class.db.command(command)
|
156
215
|
end
|
216
|
+
|
157
217
|
|
158
218
|
def self.included(receiver)
|
159
219
|
receiver.extend ClassMethods
|
160
220
|
end
|
221
|
+
|
161
222
|
end
|
223
|
+
|
224
|
+
private
|
225
|
+
# If we don't have a username AND password, returns the DB given. If we do, returns the DB if-and-only-if
|
226
|
+
# we can authenticate on that DB.
|
227
|
+
def self.maybe_authenticate(db)
|
228
|
+
if @username && @password
|
229
|
+
db if db.authenticate(@username, @password)
|
230
|
+
else
|
231
|
+
db
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
162
235
|
end
|
data/lib/candy/wrapper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'bson'
|
2
2
|
require 'date' # Only so we know what one is. Argh.
|
3
3
|
require 'candy/qualified_const_get'
|
4
4
|
|
@@ -16,10 +16,10 @@ module Candy
|
|
16
16
|
Float,
|
17
17
|
Time,
|
18
18
|
Regexp,
|
19
|
-
ByteBuffer,
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
BSON::ByteBuffer,
|
20
|
+
BSON::ObjectID,
|
21
|
+
BSON::Code,
|
22
|
+
BSON::DBRef]
|
23
23
|
|
24
24
|
# Makes an object safe for the sharp pointy edges of MongoDB. Types properly serialized
|
25
25
|
# by the BSON.serialize call get passed through unmolested; others are unpacked and their
|
@@ -28,8 +28,6 @@ module Candy
|
|
28
28
|
# Pass the simple cases through
|
29
29
|
return thing if BSON_SAFE.include?(thing.class)
|
30
30
|
case thing
|
31
|
-
# when Symbol
|
32
|
-
# wrap_symbol(thing)
|
33
31
|
when Array
|
34
32
|
wrap_array(thing)
|
35
33
|
when Hash
|
@@ -71,11 +69,6 @@ module Candy
|
|
71
69
|
wrapped
|
72
70
|
end
|
73
71
|
|
74
|
-
# Returns a string that's distinctive enough for us to unwrap later and produce the same symbol.
|
75
|
-
def self.wrap_symbol(symbol)
|
76
|
-
"__:" + symbol.to_s
|
77
|
-
end
|
78
|
-
|
79
72
|
# Returns a nested hash containing the class and instance variables of the object. It's not the
|
80
73
|
# deepest we could ever go (it doesn't handle singleton methods, etc.) but it's a start.
|
81
74
|
def self.wrap_object(object)
|
data/spec/candy/crunch_spec.rb
CHANGED
@@ -47,6 +47,8 @@ describe Candy::Crunch do
|
|
47
47
|
PeanutBrittle.connection = nil
|
48
48
|
PeanutBrittle.instance_variable_get(:@db).should be_nil
|
49
49
|
end
|
50
|
+
|
51
|
+
|
50
52
|
|
51
53
|
after(:each) do
|
52
54
|
Candy.host = nil
|
@@ -98,6 +100,39 @@ describe Candy::Crunch do
|
|
98
100
|
PeanutBrittle.instance_variable_get(:@collection).should be_nil
|
99
101
|
end
|
100
102
|
|
103
|
+
it "takes a username and password if you provide them globally" do
|
104
|
+
Mongo::DB.any_instance.expects(:authenticate).with('johnny5','is_alive').returns(true)
|
105
|
+
Candy.username = 'johnny5'
|
106
|
+
Candy.password = 'is_alive'
|
107
|
+
PeanutBrittle.db.collection_names.should_not be_nil
|
108
|
+
end
|
109
|
+
|
110
|
+
it "takes a username and password if you provide them at the class level" do
|
111
|
+
Mongo::DB.any_instance.expects(:authenticate).with('johnny5','is_alive').returns(true)
|
112
|
+
PeanutBrittle.username = 'johnny5'
|
113
|
+
PeanutBrittle.password = 'is_alive'
|
114
|
+
PeanutBrittle.db = 'candy_test'
|
115
|
+
PeanutBrittle.db.collection_names.should_not be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
it "does not authenticate if only a username is given" do
|
119
|
+
Mongo::DB.any_instance.expects(:authenticate).never
|
120
|
+
Candy.username = 'johnny5'
|
121
|
+
PeanutBrittle.db.collection_names.should_not be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
it "does not authenticate if only a password is given" do
|
126
|
+
Mongo::DB.any_instance.expects(:authenticate).never
|
127
|
+
Candy.password = 'is_alive'
|
128
|
+
PeanutBrittle.db.collection_names.should_not be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
after(:each) do
|
132
|
+
Candy.username = nil
|
133
|
+
Candy.password = nil
|
134
|
+
end
|
135
|
+
|
101
136
|
after(:all) do
|
102
137
|
Candy.db = 'candy_test' # Get back to our starting point
|
103
138
|
end
|
@@ -128,12 +163,12 @@ describe Candy::Crunch do
|
|
128
163
|
describe "index" do
|
129
164
|
it "can be created with just a property name" do
|
130
165
|
PeanutBrittle.index(:blah)
|
131
|
-
PeanutBrittle.collection.index_information.values[1].should ==
|
166
|
+
PeanutBrittle.collection.index_information.values[1]['key'].should == {"blah" => Mongo::ASCENDING}
|
132
167
|
end
|
133
168
|
|
134
169
|
it "can be created with a direction" do
|
135
170
|
PeanutBrittle.index(:fwah, :desc)
|
136
|
-
PeanutBrittle.collection.index_information.values[1].should ==
|
171
|
+
PeanutBrittle.collection.index_information.values[1]['key'].should == {"fwah" => Mongo::DESCENDING}
|
137
172
|
end
|
138
173
|
|
139
174
|
it "throws an exception if you give it a type other than :asc or :desc" do
|
data/spec/candy/piece_spec.rb
CHANGED
@@ -21,7 +21,7 @@ describe Candy::Piece do
|
|
21
21
|
|
22
22
|
it "knows its ID after inserting" do
|
23
23
|
@this.name = 'Zagnut'
|
24
|
-
@this.id.should be_a(
|
24
|
+
@this.id.should be_a(BSON::ObjectID)
|
25
25
|
end
|
26
26
|
|
27
27
|
|
@@ -112,7 +112,7 @@ describe Candy::Piece do
|
|
112
112
|
end
|
113
113
|
|
114
114
|
it "returns nil on an object that can't be found" do
|
115
|
-
id =
|
115
|
+
id = BSON::ObjectID.new
|
116
116
|
Zagnut(id).should be_nil
|
117
117
|
end
|
118
118
|
|
data/spec/candy/wrapper_spec.rb
CHANGED
@@ -50,7 +50,7 @@ module Candy
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "can wrap an ObjectID" do
|
53
|
-
i =
|
53
|
+
i = BSON::ObjectID.new
|
54
54
|
Wrapper.wrap(i).should == i
|
55
55
|
end
|
56
56
|
|
@@ -65,12 +65,12 @@ module Candy
|
|
65
65
|
end
|
66
66
|
|
67
67
|
it "can wrap a Mongo code object (if we ever need to)" do
|
68
|
-
c =
|
68
|
+
c = BSON::Code.new('5')
|
69
69
|
Wrapper.wrap(c).should == c
|
70
70
|
end
|
71
71
|
|
72
72
|
it "can wrap a Mongo DBRef (if we ever need to)" do
|
73
|
-
d =
|
73
|
+
d = BSON::DBRef.new('foo', BSON::ObjectID.new)
|
74
74
|
Wrapper.wrap(d).should == d
|
75
75
|
end
|
76
76
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 2
|
9
|
+
version: 0.2.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Stephen Eley
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-12 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: bson
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
@@ -26,15 +26,43 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
segments:
|
28
28
|
- 0
|
29
|
-
-
|
29
|
+
- 20
|
30
30
|
- 1
|
31
|
-
version: 0.
|
31
|
+
version: 0.20.1
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
35
|
+
name: bson_ext
|
36
36
|
prerelease: false
|
37
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 20
|
44
|
+
- 1
|
45
|
+
version: 0.20.1
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: mongo
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
- 20
|
58
|
+
- 1
|
59
|
+
version: 0.20.1
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
38
66
|
requirements:
|
39
67
|
- - ">="
|
40
68
|
- !ruby/object:Gem::Version
|
@@ -44,11 +72,11 @@ dependencies:
|
|
44
72
|
- 9
|
45
73
|
version: 1.2.9
|
46
74
|
type: :development
|
47
|
-
version_requirements: *
|
75
|
+
version_requirements: *id004
|
48
76
|
- !ruby/object:Gem::Dependency
|
49
77
|
name: mocha
|
50
78
|
prerelease: false
|
51
|
-
requirement: &
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
52
80
|
requirements:
|
53
81
|
- - ">="
|
54
82
|
- !ruby/object:Gem::Version
|
@@ -58,7 +86,7 @@ dependencies:
|
|
58
86
|
- 8
|
59
87
|
version: 0.9.8
|
60
88
|
type: :development
|
61
|
-
version_requirements: *
|
89
|
+
version_requirements: *id005
|
62
90
|
description: |
|
63
91
|
Candy provides simple, transparent object persistence for the MongoDB database. Classes that
|
64
92
|
include Candy modules save all properties to Mongo automatically, can be recursively embedded,
|