candy 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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 "mongo", ">= 0.19.1"
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
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.1"
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-05}
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<mongo>, [">= 0.19.1"])
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<mongo>, [">= 0.19.1"])
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<mongo>, [">= 0.19.1"])
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 => mongo_direction)
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 'mongo'
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
- Mongo::ObjectID,
21
- Mongo::Code,
22
- Mongo::DBRef]
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)
@@ -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 == [["blah", Mongo::ASCENDING]]
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 == [["fwah", Mongo::DESCENDING]]
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
@@ -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(Mongo::ObjectID)
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 = Mongo::ObjectID.new
115
+ id = BSON::ObjectID.new
116
116
  Zagnut(id).should be_nil
117
117
  end
118
118
 
@@ -50,7 +50,7 @@ module Candy
50
50
  end
51
51
 
52
52
  it "can wrap an ObjectID" do
53
- i = Mongo::ObjectID.new
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 = Mongo::Code.new('5')
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 = Mongo::DBRef.new('foo', Mongo::ObjectID.new)
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
- - 1
9
- version: 0.2.1
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-05 00:00:00 -04:00
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: mongo
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
- - 19
29
+ - 20
30
30
  - 1
31
- version: 0.19.1
31
+ version: 0.20.1
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
35
- name: rspec
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: *id002
75
+ version_requirements: *id004
48
76
  - !ruby/object:Gem::Dependency
49
77
  name: mocha
50
78
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::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: *id003
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,