candy 0.0.1

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,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Stephen Eley
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ = candy
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Stephen Eley. See LICENSE for details.
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "candy"
8
+ gem.summary = %Q{The simplest MongoDB ORM}
9
+ gem.description = <<DESCRIPTION
10
+ Candy is a lightweight ORM for the MongoDB database. If MongoMapper is Rails, Candy is Sinatra.
11
+ It provides a module you mix into any class, enabling the class to connect to Mongo on its own
12
+ and push its objects into a collection. Candied objects act like OpenStructs, allowing attributes
13
+ to be defined and updated in Mongo immediately without having to be declared in the class.
14
+ Mongo's atomic operators are used whenever possible, and a smart serializer (Candy::Wrapper)
15
+ converts almost any object for assignment to any attribute.
16
+ DESCRIPTION
17
+
18
+ gem.email = "sfeley@gmail.com"
19
+ gem.homepage = "http://github.com/SFEley/candy"
20
+ gem.authors = ["Stephen Eley"]
21
+ gem.add_dependency "mongo", ">= 0.18"
22
+ gem.add_development_dependency "rspec", ">= 1.2.9"
23
+ gem.add_development_dependency "yard", ">= 0"
24
+ gem.add_development_dependency "mocha", ">= 0.9.8"
25
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
26
+ end
27
+ Jeweler::GemcutterTasks.new
28
+ rescue LoadError
29
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
30
+ end
31
+
32
+ require 'spec/rake/spectask'
33
+ Spec::Rake::SpecTask.new(:spec) do |spec|
34
+ spec.libs << 'lib' << 'spec'
35
+ spec.spec_files = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
39
+ spec.libs << 'lib' << 'spec'
40
+ spec.pattern = 'spec/**/*_spec.rb'
41
+ spec.rcov = true
42
+ end
43
+
44
+ task :spec => :check_dependencies
45
+
46
+ task :default => :spec
47
+
48
+ begin
49
+ require 'yard'
50
+ YARD::Rake::YardocTask.new
51
+ rescue LoadError
52
+ task :yardoc do
53
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
54
+ end
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,26 @@
1
+ require 'candy/exceptions'
2
+ require 'candy/crunch'
3
+
4
+ # Mix me into your classes and Mongo will like them!
5
+ module Candy
6
+ module ClassMethods
7
+
8
+ end
9
+
10
+ module InstanceMethods
11
+ def initialize(*args, &block)
12
+ @__candy = self.class.collection.insert({})
13
+ super
14
+ end
15
+
16
+ def id
17
+ @id
18
+ end
19
+
20
+ end
21
+
22
+ def self.included(receiver)
23
+ receiver.extend ClassMethods
24
+ receiver.send :include, InstanceMethods
25
+ end
26
+ end
@@ -0,0 +1,109 @@
1
+ require 'mongo'
2
+ require 'etc'
3
+
4
+ module Candy
5
+
6
+ # All of the hard crunchy bits that connect us to a collection within a Mongo database.
7
+ module Crunch
8
+ module ClassMethods
9
+
10
+ # Passed to the default connection. It uses the $MONGO_HOST global if that's set and you don't override it.
11
+ def host
12
+ @host ||= $MONGO_HOST
13
+ end
14
+
15
+ # Passed to the default connection. It uses the $MONGO_PORT global if that's set and you don't override it.
16
+ def port
17
+ @port ||= $MONGO_PORT
18
+ end
19
+
20
+ # A hash passed to the default connection. It uses the $MONGO_OPTIONS global if that's set and you don't override it.
21
+ def options
22
+ @options ||= ($MONGO_OPTIONS || {})
23
+ end
24
+
25
+ # Overrides the host and resets the connection, db, and collection.
26
+ def host=(val)
27
+ @connection = nil
28
+ @host = val
29
+ end
30
+
31
+ # Overrides the port and resets the connection, db, and collection.
32
+ def port=(val)
33
+ @connection = nil
34
+ @port = val
35
+ end
36
+
37
+ # Overrides the options hash and resets the connection, db, and collection.
38
+ def options=(val)
39
+ @connection = nil
40
+ @options = val
41
+ end
42
+
43
+ # Returns the connection you gave, or creates a default connection to the default host and port.
44
+ def connection
45
+ @connection ||= Mongo::Connection.new(host, port, options)
46
+ end
47
+
48
+ # First clears any collection and database we're talking to, then accepts a connection you provide.
49
+ # You're responsible for your own host, port and options if you use this.
50
+ def connection=(val)
51
+ self.db = nil
52
+ @connection = val
53
+ end
54
+
55
+ # First clears any collection we're talking to, then accepts a database you provide. You can provide a
56
+ # Mongo::DB object or a string with the database name. If you provide a Mongo::DB object, the default
57
+ # connection is not used, and the :strict flag should be false or default collection lookup will fail.
58
+ def db=(val)
59
+ self.collection = nil
60
+ case val
61
+ when Mongo::DB
62
+ @db = val
63
+ when String
64
+ @db = Mongo::DB.new(val, connection)
65
+ when nil
66
+ @db = nil
67
+ else
68
+ raise ConnectionError, "The db attribute needs a Mongo::DB object or a name string."
69
+ end
70
+ end
71
+
72
+ # Returns the database you gave, or creates a default database named for your username (or 'candy' if it
73
+ # can't find a username).
74
+ def db
75
+ @db ||= Mongo::DB.new($MONGO_DB || Etc.getlogin || 'candy', connection, :strict => false)
76
+ end
77
+
78
+ # Accepts either a Mongo::Collection object or a string with the collection name. If you provide a
79
+ # Mongo::Collection object, the default database and connection are not used.
80
+ def collection=(val)
81
+ case val
82
+ when Mongo::Collection
83
+ @collection = val
84
+ when String
85
+ @collection = db.create_collection(val)
86
+ when nil
87
+ @collection = nil
88
+ else
89
+ raise ConnectionError, "The collection attribute needs a Mongo::Collection object or a name string."
90
+ end
91
+ end
92
+
93
+ # Returns the collection you gave, or creates a default collection named for the current class.
94
+ def collection
95
+ @collection ||= db.create_collection(name)
96
+ end
97
+
98
+ end
99
+
100
+ module InstanceMethods
101
+
102
+ end
103
+
104
+ def self.included(receiver)
105
+ receiver.extend ClassMethods
106
+ receiver.send :include, InstanceMethods
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ module Candy
3
+ # Every other exception type falls under CandyError for easy catching.
4
+ class CandyError < StandardError; end
5
+
6
+ class ConnectionError < CandyError; end
7
+ end
@@ -0,0 +1,151 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'logger'
3
+
4
+ describe Candy::Crunch do
5
+
6
+ class PeanutBrittle
7
+ include Candy::Crunch
8
+ end
9
+
10
+
11
+ describe "connection" do
12
+ before(:each) do
13
+ # Make sure we don't waste time making bogus connections
14
+ PeanutBrittle.options[:connect] = false
15
+ end
16
+
17
+ it "takes yours if you give it one" do
18
+ c = Mongo::Connection.new('example.org', 11111, :connect => false)
19
+ PeanutBrittle.connection = c
20
+ PeanutBrittle.connection.nodes.should == [["example.org", 11111]]
21
+ end
22
+
23
+ it "creates the default connection if you don't give it one" do
24
+ PeanutBrittle.connection.nodes.should == [["localhost", 27017]]
25
+ end
26
+
27
+ it "uses the host you provide" do
28
+ PeanutBrittle.host = 'example.org'
29
+ PeanutBrittle.connection.nodes.should == [["example.org", 27017]]
30
+ end
31
+
32
+ it "uses the port you provide" do
33
+ PeanutBrittle.host = 'localhost'
34
+ PeanutBrittle.port = 3000
35
+ PeanutBrittle.connection.nodes.should == [["localhost", 3000]]
36
+ end
37
+
38
+ it "uses any options you provide" do
39
+ l = Logger.new(STDOUT)
40
+ PeanutBrittle.options[:logger] = l
41
+ PeanutBrittle.connection.logger.should == l
42
+ end
43
+
44
+ it "uses the $MONGO_HOST setting if you don't override it" do
45
+ $MONGO_HOST = 'example.net'
46
+ PeanutBrittle.connection.nodes.should == [["example.net", 27017]]
47
+ end
48
+
49
+ it "uses the $MONGO_PORT setting if you don't override it" do
50
+ PeanutBrittle.host = 'localhost'
51
+ $MONGO_PORT = 33333
52
+ PeanutBrittle.connection.nodes.should == [["localhost", 33333]]
53
+ end
54
+
55
+ it "uses the $MONGO_OPTIONS setting if you don't override it" do
56
+ l = Logger.new(STDOUT)
57
+ PeanutBrittle.options = nil # Gotta be careful of our order on this one
58
+ $MONGO_OPTIONS = {:logger => l, :connect => false}
59
+ PeanutBrittle.connection.logger.should == $MONGO_OPTIONS[:logger]
60
+ end
61
+
62
+ it "clears the database when you set it" do
63
+ PeanutBrittle.db.name.should == 'candy_test'
64
+ PeanutBrittle.connection = nil
65
+ PeanutBrittle.instance_variable_get(:@db).should be_nil
66
+ end
67
+
68
+ after(:each) do
69
+ $MONGO_HOST = nil
70
+ $MONGO_PORT = nil
71
+ $MONGO_OPTIONS = nil
72
+ PeanutBrittle.host = nil
73
+ PeanutBrittle.port = nil
74
+ PeanutBrittle.options = nil
75
+ end
76
+ end
77
+
78
+ describe "database" do
79
+ before(:each) do
80
+ $MONGO_DB = nil
81
+ end
82
+
83
+ it "takes yours if you give it one" do
84
+ d = Mongo::DB.new('test', PeanutBrittle.connection)
85
+ PeanutBrittle.db = d
86
+ PeanutBrittle.db.name.should == 'test'
87
+ end
88
+
89
+ it "takes a name if you give it one" do
90
+ PeanutBrittle.db = 'crunchy'
91
+ PeanutBrittle.db.name.should == 'crunchy'
92
+ end
93
+
94
+ it "throws an exception if you give it a database type it can't recognize" do
95
+ lambda{PeanutBrittle.db = 5}.should raise_error(Candy::ConnectionError, "The db attribute needs a Mongo::DB object or a name string.")
96
+ end
97
+
98
+ it "uses the $MONGO_DB setting if you don't override it" do
99
+ $MONGO_DB = 'foobar'
100
+ PeanutBrittle.db.name.should == 'foobar'
101
+ end
102
+
103
+ it "uses your username if you don't give it a default database" do
104
+ Etc.stubs(:getlogin).returns('nummymuffin')
105
+ PeanutBrittle.db.name.should == 'nummymuffin'
106
+ end
107
+
108
+ it "uses 'candy' for a DB name if it can't find a username" do
109
+ Etc.expects(:getlogin).returns(nil)
110
+ PeanutBrittle.db.name.should == 'candy'
111
+ end
112
+
113
+ it "clears the collection when you set it" do
114
+ PeanutBrittle.db = 'candy_test'
115
+ PeanutBrittle.collection.name.should == PeanutBrittle.name
116
+ PeanutBrittle.db = nil
117
+ PeanutBrittle.instance_variable_get(:@collection).should be_nil
118
+ end
119
+
120
+ after(:all) do
121
+ $MONGO_DB = 'candy_test' # Get back to our starting point
122
+ end
123
+ end
124
+
125
+ describe "collection" do
126
+ it "takes yours if you give it one" do
127
+ c = Mongo::Collection.new(PeanutBrittle.db, 'blah')
128
+ PeanutBrittle.collection = c
129
+ PeanutBrittle.collection.name.should == 'blah'
130
+ end
131
+
132
+ it "takes a name if you give it one" do
133
+ PeanutBrittle.collection = 'bleh'
134
+ PeanutBrittle.collection.name.should == 'bleh'
135
+ end
136
+
137
+ it "defaults to the class name" do
138
+ PeanutBrittle.collection.name.should == PeanutBrittle.name
139
+ end
140
+
141
+ it "throws an exception if you give it a type it can't recognize" do
142
+ lambda{PeanutBrittle.collection = 17.3}.should raise_error(Candy::ConnectionError, "The collection attribute needs a Mongo::Collection object or a name string.")
143
+ end
144
+
145
+ end
146
+
147
+ after(:each) do
148
+ PeanutBrittle.connection = nil
149
+ end
150
+
151
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Candy" do
4
+ # An example class to contain our methods
5
+ class Zagnut
6
+ include Candy
7
+ end
8
+
9
+ before(:each) do
10
+ @this = Zagnut.new
11
+ end
12
+
13
+ it "inserts a document immediately" do
14
+ @this.id.should be_a(Mongo::ObjectID)
15
+ end
16
+
17
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,12 @@
1
+ # See: http://github.com/mynyml/watchr/
2
+
3
+ require 'redgreen'
4
+ require 'autowatchr'
5
+
6
+ Autowatchr.new(self) do |config|
7
+ config.test_dir = 'spec'
8
+ config.test_re = "^#{config.test_dir}/(.*)_spec\.rb$"
9
+ config.test_file = '%s_spec.rb'
10
+ end
11
+ # watch ( 'spec/.*_spec\.rb' ) { |spec| system("ruby #{spec[0]}")}
12
+ # watch ( 'lib/(.*).rb' ) { |lib| system("ruby spec/#{spec[1]}_spec.rb")}
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'candy'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'mocha'
7
+
8
+ Spec::Runner.configure do |config|
9
+ config.mock_with :mocha
10
+
11
+ config.before(:all) do
12
+ $MONGO_DB = 'candy_test'
13
+ end
14
+
15
+ config.after(:all) do
16
+ c = Mongo::Connection.new
17
+ c.drop_database('candy_test')
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: candy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Eley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-20 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mongo
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0.18"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.9
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: yard
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: mocha
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.8
54
+ version:
55
+ description: |
56
+ Candy is a lightweight ORM for the MongoDB database. If MongoMapper is Rails, Candy is Sinatra.
57
+ It provides a module you mix into any class, enabling the class to connect to Mongo on its own
58
+ and push its objects into a collection. Candied objects act like OpenStructs, allowing attributes
59
+ to be defined and updated in Mongo immediately without having to be declared in the class.
60
+ Mongo's atomic operators are used whenever possible, and a smart serializer (Candy::Wrapper)
61
+ converts almost any object for assignment to any attribute.
62
+
63
+ email: sfeley@gmail.com
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files:
69
+ - LICENSE
70
+ - README.rdoc
71
+ files:
72
+ - .document
73
+ - .gitignore
74
+ - LICENSE
75
+ - README.rdoc
76
+ - Rakefile
77
+ - VERSION
78
+ - lib/candy.rb
79
+ - lib/candy/crunch.rb
80
+ - lib/candy/exceptions.rb
81
+ - spec/candy/crunch_spec.rb
82
+ - spec/candy_spec.rb
83
+ - spec/spec.opts
84
+ - spec/spec.watchr
85
+ - spec/spec_helper.rb
86
+ has_rdoc: true
87
+ homepage: http://github.com/SFEley/candy
88
+ licenses: []
89
+
90
+ post_install_message:
91
+ rdoc_options:
92
+ - --charset=UTF-8
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ version:
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: "0"
106
+ version:
107
+ requirements: []
108
+
109
+ rubyforge_project:
110
+ rubygems_version: 1.3.5
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: The simplest MongoDB ORM
114
+ test_files:
115
+ - spec/candy/crunch_spec.rb
116
+ - spec/candy_spec.rb
117
+ - spec/spec_helper.rb