mongo_doc 0.3.0
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/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.textile +174 -0
- data/Rakefile +135 -0
- data/TODO +31 -0
- data/VERSION +1 -0
- data/data/.gitignore +2 -0
- data/examples/simple_document.rb +35 -0
- data/examples/simple_object.rb +30 -0
- data/features/finders.feature +76 -0
- data/features/mongodb.yml +7 -0
- data/features/mongodoc_base.feature +128 -0
- data/features/new_record.feature +36 -0
- data/features/partial_updates.feature +105 -0
- data/features/removing_documents.feature +68 -0
- data/features/saving_an_object.feature +15 -0
- data/features/scopes.feature +66 -0
- data/features/step_definitions/collection_steps.rb +14 -0
- data/features/step_definitions/document_steps.rb +149 -0
- data/features/step_definitions/documents.rb +30 -0
- data/features/step_definitions/finder_steps.rb +15 -0
- data/features/step_definitions/json_steps.rb +9 -0
- data/features/step_definitions/object_steps.rb +50 -0
- data/features/step_definitions/objects.rb +24 -0
- data/features/step_definitions/partial_update_steps.rb +32 -0
- data/features/step_definitions/query_steps.rb +54 -0
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/step_definitions/scope_steps.rb +18 -0
- data/features/step_definitions/util_steps.rb +7 -0
- data/features/support/support.rb +10 -0
- data/features/using_criteria.feature +128 -0
- data/lib/mongo_doc/associations/collection_proxy.rb +105 -0
- data/lib/mongo_doc/associations/document_proxy.rb +56 -0
- data/lib/mongo_doc/associations/hash_proxy.rb +98 -0
- data/lib/mongo_doc/associations/proxy_base.rb +53 -0
- data/lib/mongo_doc/attributes.rb +140 -0
- data/lib/mongo_doc/bson.rb +45 -0
- data/lib/mongo_doc/collection.rb +55 -0
- data/lib/mongo_doc/connection.rb +88 -0
- data/lib/mongo_doc/contexts/enumerable.rb +128 -0
- data/lib/mongo_doc/contexts/ids.rb +41 -0
- data/lib/mongo_doc/contexts/mongo.rb +232 -0
- data/lib/mongo_doc/contexts.rb +25 -0
- data/lib/mongo_doc/criteria.rb +38 -0
- data/lib/mongo_doc/cursor.rb +32 -0
- data/lib/mongo_doc/document.rb +216 -0
- data/lib/mongo_doc/ext/array.rb +5 -0
- data/lib/mongo_doc/ext/binary.rb +7 -0
- data/lib/mongo_doc/ext/boolean_class.rb +11 -0
- data/lib/mongo_doc/ext/date.rb +16 -0
- data/lib/mongo_doc/ext/date_time.rb +13 -0
- data/lib/mongo_doc/ext/dbref.rb +7 -0
- data/lib/mongo_doc/ext/hash.rb +7 -0
- data/lib/mongo_doc/ext/nil_class.rb +5 -0
- data/lib/mongo_doc/ext/numeric.rb +17 -0
- data/lib/mongo_doc/ext/object.rb +17 -0
- data/lib/mongo_doc/ext/object_id.rb +7 -0
- data/lib/mongo_doc/ext/regexp.rb +5 -0
- data/lib/mongo_doc/ext/string.rb +5 -0
- data/lib/mongo_doc/ext/symbol.rb +5 -0
- data/lib/mongo_doc/ext/time.rb +5 -0
- data/lib/mongo_doc/finders.rb +49 -0
- data/lib/mongo_doc/matchers.rb +35 -0
- data/lib/mongo_doc/query.rb +7 -0
- data/lib/mongo_doc/scope.rb +64 -0
- data/lib/mongo_doc/validations/macros.rb +11 -0
- data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
- data/lib/mongo_doc.rb +19 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +247 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +92 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/mongo_doc.gemspec +205 -0
- data/mongod.example.yml +2 -0
- data/mongodb.example.yml +14 -0
- data/perf/mongo_doc_runner.rb +90 -0
- data/perf/ruby_driver_runner.rb +64 -0
- data/script/console +8 -0
- data/spec/associations/collection_proxy_spec.rb +200 -0
- data/spec/associations/document_proxy_spec.rb +42 -0
- data/spec/associations/hash_proxy_spec.rb +163 -0
- data/spec/attributes_spec.rb +273 -0
- data/spec/bson_matchers.rb +54 -0
- data/spec/bson_spec.rb +196 -0
- data/spec/collection_spec.rb +161 -0
- data/spec/connection_spec.rb +147 -0
- data/spec/contexts/enumerable_spec.rb +274 -0
- data/spec/contexts/ids_spec.rb +49 -0
- data/spec/contexts/mongo_spec.rb +198 -0
- data/spec/contexts_spec.rb +28 -0
- data/spec/criteria_spec.rb +33 -0
- data/spec/cursor_spec.rb +91 -0
- data/spec/document_ext.rb +9 -0
- data/spec/document_spec.rb +664 -0
- data/spec/embedded_save_spec.rb +109 -0
- data/spec/finders_spec.rb +73 -0
- data/spec/hash_matchers.rb +27 -0
- data/spec/matchers_spec.rb +342 -0
- data/spec/mongodb.yml +6 -0
- data/spec/mongodb_pairs.yml +8 -0
- data/spec/new_record_spec.rb +128 -0
- data/spec/query_spec.rb +12 -0
- data/spec/scope_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +13 -0
- metadata +290 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 Les Hill
|
|
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.
|
data/README.textile
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
h1. MongoDoc
|
|
2
|
+
|
|
3
|
+
Version: 0.2.4 2/23/10
|
|
4
|
+
|
|
5
|
+
2010-02-23 API is *changing* significantly
|
|
6
|
+
2010-01-23 Tracking MongoDoc with @git@? *READ THIS NOTE*[1]
|
|
7
|
+
|
|
8
|
+
h2. Introduction
|
|
9
|
+
|
|
10
|
+
MongoDoc is a simple and easy to use ActiveRecord-like object mapper for "mongoDB":http://www.mongodb.org in Ruby.
|
|
11
|
+
|
|
12
|
+
MongoDoc is _also_ an extension of the "Mongo Ruby Driver":http://github.com/mongodb/mongo-ruby-driver making it a snap to get Ruby in and out of mongoDB.
|
|
13
|
+
|
|
14
|
+
MongoDoc is *not* ActiveRecord for mongoDB. We do not have callbacks, nor do we have dynamic finders. We do have associations, named scopes, and other features.
|
|
15
|
+
|
|
16
|
+
MongoDoc *is* simple, easy-to-use, and fast. And it works with Rails (2.3.x at the moment, 3 soonish?).
|
|
17
|
+
|
|
18
|
+
MongoDoc is designed to work with document data, if you are looking to map relational data in mongoDB, you will have to look elsewhere.
|
|
19
|
+
|
|
20
|
+
h2. Ruby objects in mongoDB
|
|
21
|
+
|
|
22
|
+
Lets just get right into it and save some Ruby objects in mongoDB!
|
|
23
|
+
|
|
24
|
+
bc.. class Contact
|
|
25
|
+
attr_accessor :name, :addresses, :interests
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Address
|
|
29
|
+
attr_accessor :street, :city, :state, :zip, :phone_number
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
p. With MongoDoc, instead of saving JSON[2], we can save an object directly:
|
|
33
|
+
|
|
34
|
+
bc.. contact = Contact.new
|
|
35
|
+
contact.name = 'Hashrocket'
|
|
36
|
+
contact.interests = ['ruby', 'rails', 'agile']
|
|
37
|
+
|
|
38
|
+
address = Address.new
|
|
39
|
+
address.street = '320 First Street North, #712'
|
|
40
|
+
address.city = 'Jacksonville Beach'
|
|
41
|
+
address.state = 'FL'
|
|
42
|
+
address.zip = '32250'
|
|
43
|
+
address.phone_number = '877 885 8846'
|
|
44
|
+
contact.addresses = [address]
|
|
45
|
+
|
|
46
|
+
collection.save(contact)
|
|
47
|
+
|
|
48
|
+
p. We can query using the powerful mongoDB query syntax, and have it return Ruby objects:
|
|
49
|
+
|
|
50
|
+
bc.. results = collection.find('addresses.state' => 'FL')
|
|
51
|
+
hashrocket = results.to_a.find {|contact| contact.name == 'Hashrocket'}
|
|
52
|
+
puts hashrocket.addresses.first.phone_number
|
|
53
|
+
|
|
54
|
+
p. Take a look in the examples directory for more code.
|
|
55
|
+
|
|
56
|
+
h2. Mapping Documents
|
|
57
|
+
|
|
58
|
+
MongoDoc provides ActiveRecord-like persistence, associations, named scopes, and validations (from "Validatable":http://github.com/durran/validatable) as well as a mongoDB query language (from "Mongoid":http://mongoid.org/home). MongoDoc also plays nicely with Rails.
|
|
59
|
+
|
|
60
|
+
@MongoDoc::Document@ provides all these features as a mixin. A @MongoDoc::Document@ can either be a top-level mongoDB document, or an embedded document contained within a top-level document. Top-level documents are stored in collections named after their class: @Contact@ objects are stored in the 'contacts' collection (much like ActiveRecord).
|
|
61
|
+
|
|
62
|
+
Lets define a @Contact@ document with an @Address@ embedded document:
|
|
63
|
+
|
|
64
|
+
bc.. class Address
|
|
65
|
+
include MongoDoc::Document
|
|
66
|
+
|
|
67
|
+
key :street
|
|
68
|
+
key :city
|
|
69
|
+
key :state
|
|
70
|
+
key :zip_code
|
|
71
|
+
key :phone_number
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class Contact
|
|
75
|
+
include MongoDoc::Document
|
|
76
|
+
|
|
77
|
+
key :name
|
|
78
|
+
key :interests
|
|
79
|
+
has_many :addresses
|
|
80
|
+
|
|
81
|
+
named_scope :in_state, lambda {|state| {:where => {'addresses.state' => state}}}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
p. Since a mongoDB document has no fixed schema, we define the composition of a document directly in our classes. Please note we do not specify types! We can also specify @has_one@ or @has_many@ associations.
|
|
85
|
+
|
|
86
|
+
Building and saving a document is easy:
|
|
87
|
+
|
|
88
|
+
bc.. contact = Contact.new(:name => 'Hashrocket', :interests => ['ruby', 'rails', 'agile'])
|
|
89
|
+
contact.addresses << Address.new(:street => '320 1st Street North, #712',
|
|
90
|
+
:city => 'Jacksonville Beach',
|
|
91
|
+
:state => 'FL',
|
|
92
|
+
:zip_code => '32250',
|
|
93
|
+
:phone_number => '877 885 8846')
|
|
94
|
+
contact.save
|
|
95
|
+
|
|
96
|
+
p. Now that we have some data, we can query using our named scope:
|
|
97
|
+
|
|
98
|
+
bc. hashrocket = Contact.in_state('FL').find {|contact| contact.name == 'Hashrocket'}
|
|
99
|
+
|
|
100
|
+
p. And we can even perform partial updates:
|
|
101
|
+
|
|
102
|
+
bc. hashrocket.addresses.first.update_attributes(:street => '320 First Street North, #712')
|
|
103
|
+
|
|
104
|
+
h2. Installation
|
|
105
|
+
|
|
106
|
+
MongoDoc *requires* mongoDB v1.3.2 or later.
|
|
107
|
+
|
|
108
|
+
bc. sudo gem install mongodoc
|
|
109
|
+
|
|
110
|
+
h2. Connecting
|
|
111
|
+
|
|
112
|
+
By default, MongoDoc will read its configuration from @./mongodb.yml@. If that file does not exist, it will attempt to connect to a standard MongoDB local server setup and use a database name of @"mongodoc"@.
|
|
113
|
+
|
|
114
|
+
h3. With Rails
|
|
115
|
+
|
|
116
|
+
If you are using Rails, MongoDoc will look for its configuration in @config/mongodb.yml@. If that file does not exist, it will attempt to connect to a standard MongoDB local server setup and use a database name of @#{Rails.root.basename}_#{Rails.env}@.
|
|
117
|
+
|
|
118
|
+
h3. Database configuration file
|
|
119
|
+
|
|
120
|
+
The file is similar to the Rails database.yml file, with environment definitions containing the database configuration attributes. For example:
|
|
121
|
+
|
|
122
|
+
bc. development:
|
|
123
|
+
name: development
|
|
124
|
+
host: localhost
|
|
125
|
+
port: 27017
|
|
126
|
+
options:
|
|
127
|
+
auto_reconnect: true
|
|
128
|
+
test:
|
|
129
|
+
name: test
|
|
130
|
+
host: localhost
|
|
131
|
+
port: 27017
|
|
132
|
+
options:
|
|
133
|
+
auto_reconnect: true
|
|
134
|
+
|
|
135
|
+
If you are not using Rails, the default environment is @development@ and you can set the current environment in your code:
|
|
136
|
+
|
|
137
|
+
bc. MongoDoc::Connection.env = 'test'
|
|
138
|
+
|
|
139
|
+
You can also change the location of the configuration file:
|
|
140
|
+
|
|
141
|
+
bc. MongoDoc::Connection.config_path = './config/mongodb.yml'
|
|
142
|
+
|
|
143
|
+
h3. Programmatically setting the database connection information
|
|
144
|
+
|
|
145
|
+
Finally, if you do not want to use the database configuration file, you can also set the database name, host, port, options, and strict values directly; for example, to set the database name to @stats@:
|
|
146
|
+
|
|
147
|
+
bc. MongoDoc::Connection.name = 'stats'
|
|
148
|
+
|
|
149
|
+
h2. Credits
|
|
150
|
+
|
|
151
|
+
Les Hill, leshill on github
|
|
152
|
+
|
|
153
|
+
h3. Thanks
|
|
154
|
+
|
|
155
|
+
Thanks to Sandro and Durran for some great conversations and some lovely code.
|
|
156
|
+
|
|
157
|
+
h2. Note on Patches/Pull Requests
|
|
158
|
+
|
|
159
|
+
* Fork the project.
|
|
160
|
+
* Make your feature addition or bug fix.
|
|
161
|
+
* Add tests for it. This is important so I don't break it in a
|
|
162
|
+
future version unintentionally.
|
|
163
|
+
* Commit, do not mess with rakefile, version, or history.
|
|
164
|
+
(if you want to have your own version, that is fine but
|
|
165
|
+
bump version in a commit by itself I can ignore when I pull)
|
|
166
|
+
* Send me a pull request. Bonus points for topic branches.
|
|
167
|
+
|
|
168
|
+
h2. Copyright
|
|
169
|
+
|
|
170
|
+
Copyright (c) 2009 - 2010 Les Hill. See LICENSE for details.
|
|
171
|
+
|
|
172
|
+
fn1. Building from @HEAD@? MongoDoc *requires* mongoDB v1.3.2 or later. That means you must be using the 1.3.x nightly build as of 2010-01-22 .
|
|
173
|
+
|
|
174
|
+
fn2. The Ruby driver exposes an API that understands JSON.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'jeweler'
|
|
6
|
+
Jeweler::Tasks.new do |gem|
|
|
7
|
+
gem.name = "mongo_doc"
|
|
8
|
+
gem.summary = %Q{ODM for MongoDB}
|
|
9
|
+
gem.description = %Q{ODM for MongoDB}
|
|
10
|
+
gem.email = "leshill@gmail.com"
|
|
11
|
+
gem.homepage = "http://github.com/leshill/mongodoc"
|
|
12
|
+
gem.authors = ["Les Hill"]
|
|
13
|
+
gem.add_dependency "mongo", "= 0.19"
|
|
14
|
+
gem.add_dependency "mongo_ext", "= 0.19"
|
|
15
|
+
gem.add_dependency "durran-validatable", "= 2.0.1"
|
|
16
|
+
gem.add_dependency "leshill-will_paginate", "= 2.3.11"
|
|
17
|
+
gem.add_development_dependency "rspec", "= 1.3.0"
|
|
18
|
+
gem.add_development_dependency "cucumber", "= 0.6.2"
|
|
19
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
20
|
+
end
|
|
21
|
+
Jeweler::GemcutterTasks.new
|
|
22
|
+
rescue LoadError
|
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
require 'cucumber/rake/task'
|
|
27
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
|
28
|
+
t.cucumber_opts = "--format pretty --tag ~@wip"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
namespace :cucumber do
|
|
32
|
+
Cucumber::Rake::Task.new(:wip) do |t|
|
|
33
|
+
t.cucumber_opts = "--format pretty --tag @wip"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
require 'spec/rake/spectask'
|
|
38
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
|
39
|
+
spec.spec_opts = ['--options', "#{File.expand_path(File.dirname(__FILE__))}/spec/spec.opts"]
|
|
40
|
+
spec.libs << 'lib' << 'spec'
|
|
41
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
45
|
+
spec.spec_opts = ['--options', "#{File.expand_path(File.dirname(__FILE__))}/spec/spec.opts"]
|
|
46
|
+
spec.libs << 'lib' << 'spec'
|
|
47
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
48
|
+
spec.rcov = true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
task :spec => :check_dependencies
|
|
52
|
+
|
|
53
|
+
task :default => :spec
|
|
54
|
+
|
|
55
|
+
require 'rake/rdoctask'
|
|
56
|
+
Rake::RDocTask.new do |rdoc|
|
|
57
|
+
if File.exist?('VERSION')
|
|
58
|
+
version = File.read('VERSION')
|
|
59
|
+
else
|
|
60
|
+
version = ""
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
64
|
+
rdoc.title = "MongoDoc #{version}"
|
|
65
|
+
rdoc.rdoc_files.include('README*')
|
|
66
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
namespace :mongo do
|
|
70
|
+
desc 'Start mongod'
|
|
71
|
+
task :start do
|
|
72
|
+
default_config = { "dbpath" => "/data/db" }
|
|
73
|
+
config = begin
|
|
74
|
+
YAML.load_file(File.join(File.dirname(__FILE__), 'mongod.yml'))
|
|
75
|
+
rescue Exception => e
|
|
76
|
+
{}
|
|
77
|
+
end
|
|
78
|
+
config = default_config.merge(config)
|
|
79
|
+
sh("nohup #{config['mongod'] || 'mongod'} --dbpath #{config['dbpath']} &")
|
|
80
|
+
puts "\n"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
namespace :mongoid do
|
|
85
|
+
desc 'Sync criteria from Mongoid'
|
|
86
|
+
task :sync do
|
|
87
|
+
require 'pathname'
|
|
88
|
+
|
|
89
|
+
src_dir = Pathname.new('../durran-mongoid/lib/mongoid')
|
|
90
|
+
dest_dir = Pathname.new('lib/mongoid')
|
|
91
|
+
dest_dir.mkpath
|
|
92
|
+
%w(criteria.rb contexts/paging.rb criterion extensions/symbol/inflections.rb extensions/hash/criteria_helpers.rb matchers).each do |f|
|
|
93
|
+
src = src_dir + f
|
|
94
|
+
if src.directory?
|
|
95
|
+
FileUtils.cp_r(src, dest_dir)
|
|
96
|
+
else
|
|
97
|
+
dest = dest_dir + f
|
|
98
|
+
dest.dirname.mkpath
|
|
99
|
+
FileUtils.cp(src, dest)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
namespace :bench do
|
|
106
|
+
desc 'Run benchmark for MongoDoc'
|
|
107
|
+
task 'mongo_doc' do
|
|
108
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
109
|
+
require 'perf/mongo_doc_runner'
|
|
110
|
+
MongoDocRunner.benchmark
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
desc 'Run profiler for driver'
|
|
114
|
+
task 'driver' do
|
|
115
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
116
|
+
require 'perf/ruby_driver_runner'
|
|
117
|
+
RubyDriverRunner.benchmark
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
namespace :prof do
|
|
122
|
+
desc 'Run profiler for MongoDoc'
|
|
123
|
+
task 'mongo_doc' do
|
|
124
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
125
|
+
require 'perf/mongo_doc_runner'
|
|
126
|
+
MongoDocRunner.profile
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
desc 'Run profiler for driver'
|
|
130
|
+
task 'driver' do
|
|
131
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
132
|
+
require 'perf/ruby_driver_runner'
|
|
133
|
+
RubyDriverRunner.profile
|
|
134
|
+
end
|
|
135
|
+
end
|
data/TODO
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
As of 2010-02-23
|
|
2
|
+
|
|
3
|
+
Associations
|
|
4
|
+
------------
|
|
5
|
+
|
|
6
|
+
Pull associations out of attributes and refactor
|
|
7
|
+
|
|
8
|
+
Criteria
|
|
9
|
+
--------
|
|
10
|
+
|
|
11
|
+
Make critieria module, include into Document, CriteriaProxy, Association?
|
|
12
|
+
|
|
13
|
+
Documentation
|
|
14
|
+
-------------
|
|
15
|
+
|
|
16
|
+
How to get started with Rails
|
|
17
|
+
Using mongohq
|
|
18
|
+
|
|
19
|
+
Dynamic Attributes
|
|
20
|
+
------------------
|
|
21
|
+
|
|
22
|
+
Document#[] => reads attribute
|
|
23
|
+
Document#[]= => writes attribute
|
|
24
|
+
Document#dynamic_attributes => key, value for each dynamic attribute
|
|
25
|
+
Document#dynamic_attribute_names => list of dynamic attribute names
|
|
26
|
+
|
|
27
|
+
Validations
|
|
28
|
+
-----------
|
|
29
|
+
|
|
30
|
+
validates_hash_keys :has_hash_name, :in => [array of names]
|
|
31
|
+
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.3.0
|
data/data/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'mongo_doc'
|
|
2
|
+
|
|
3
|
+
class Address
|
|
4
|
+
include MongoDoc::Document
|
|
5
|
+
|
|
6
|
+
key :street
|
|
7
|
+
key :city
|
|
8
|
+
key :state
|
|
9
|
+
key :zip_code
|
|
10
|
+
key :phone_number
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Contact
|
|
14
|
+
include MongoDoc::Document
|
|
15
|
+
|
|
16
|
+
key :name
|
|
17
|
+
key :interests
|
|
18
|
+
has_many :addresses
|
|
19
|
+
|
|
20
|
+
scope :in_state, lambda {|state| where('addresses.state' => state)}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
Contact.collection.drop
|
|
24
|
+
|
|
25
|
+
contact = Contact.new(:name => 'Hashrocket', :interests => ['ruby', 'rails', 'agile'])
|
|
26
|
+
contact.addresses << Address.new(:street => '320 1st Street North, #712', :city => 'Jacksonville Beach', :state => 'FL', :zip_code => '32250', :phone_number => '877 885 8846')
|
|
27
|
+
contact.save
|
|
28
|
+
puts Contact.find_one(contact.to_param).addresses.first.street
|
|
29
|
+
|
|
30
|
+
hashrocket = Contact.in_state('FL').find {|contact| contact.name == 'Hashrocket'}
|
|
31
|
+
|
|
32
|
+
hashrocket_address = hashrocket.addresses.first
|
|
33
|
+
hashrocket_address.update_attributes(:street => '320 First Street North, #712')
|
|
34
|
+
|
|
35
|
+
puts Contact.where(:name => 'Hashrocket').first.addresses.first.street
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'mongo_doc'
|
|
2
|
+
|
|
3
|
+
class Contact
|
|
4
|
+
attr_accessor :name, :addresses, :interests
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class Address
|
|
8
|
+
attr_accessor :street, :city, :state, :zip, :phone_number
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
collection = MongoDoc::Collection.new('contacts')
|
|
12
|
+
collection.drop
|
|
13
|
+
|
|
14
|
+
contact = Contact.new
|
|
15
|
+
contact.name = 'Hashrocket'
|
|
16
|
+
contact.interests = ['ruby', 'rails', 'agile']
|
|
17
|
+
|
|
18
|
+
address = Address.new
|
|
19
|
+
address.street = '320 First Street North, #712'
|
|
20
|
+
address.city = 'Jacksonville Beach'
|
|
21
|
+
address.state = 'FL'
|
|
22
|
+
address.zip = '32250'
|
|
23
|
+
address.phone_number = '877 885 8846'
|
|
24
|
+
contact.addresses = [address]
|
|
25
|
+
|
|
26
|
+
collection.save(contact)
|
|
27
|
+
|
|
28
|
+
results = collection.find('addresses.state' => 'FL')
|
|
29
|
+
hashrocket = results.to_a.find {|contact| contact.name == 'Hashrocket'}
|
|
30
|
+
puts hashrocket.addresses.first.phone_number
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Feature: Finders
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given an empty Contact document collection
|
|
5
|
+
And a Contact document named 'hashrocket' :
|
|
6
|
+
| Name | Type |
|
|
7
|
+
| Hashrocket | company |
|
|
8
|
+
And 'hashrocket' has interests, an array of:
|
|
9
|
+
| Interest |
|
|
10
|
+
| ruby |
|
|
11
|
+
| rails |
|
|
12
|
+
| employment |
|
|
13
|
+
| contract work |
|
|
14
|
+
| restaurants |
|
|
15
|
+
| hotels |
|
|
16
|
+
| flights |
|
|
17
|
+
| car rentals |
|
|
18
|
+
And 'hashrocket' has many addresses :
|
|
19
|
+
| Street | City | State | Zip Code |
|
|
20
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
21
|
+
| 1 Lake Michigan Street | Chicago | IL | 60611 |
|
|
22
|
+
| 1 Main Street | Santiago | Chile | |
|
|
23
|
+
And I save the document 'hashrocket'
|
|
24
|
+
And a Contact document named 'rocketeer' :
|
|
25
|
+
| Name |
|
|
26
|
+
| Rocketeer Mike |
|
|
27
|
+
And 'rocketeer' has interests, an array of:
|
|
28
|
+
| Interest |
|
|
29
|
+
| ruby |
|
|
30
|
+
| rails |
|
|
31
|
+
| restaurants |
|
|
32
|
+
| employment |
|
|
33
|
+
And 'rocketeer' has many addresses :
|
|
34
|
+
| Street | City | State | Zip Code |
|
|
35
|
+
| 1 Main Street | Atlantic Beach | FL | 32233 |
|
|
36
|
+
And I save the document 'rocketeer'
|
|
37
|
+
And a Contact document named 'contractor' :
|
|
38
|
+
| Name |
|
|
39
|
+
| Contractor Joe |
|
|
40
|
+
And 'contractor' has interests, an array of:
|
|
41
|
+
| Interest |
|
|
42
|
+
| ruby |
|
|
43
|
+
| rails |
|
|
44
|
+
| contract work |
|
|
45
|
+
| flights |
|
|
46
|
+
| car rentals |
|
|
47
|
+
| hotels |
|
|
48
|
+
| restaurants |
|
|
49
|
+
And 'contractor' has many addresses :
|
|
50
|
+
| Street | City | State | Zip Code |
|
|
51
|
+
| 1 Main St. | Jacksonville | FL | 32218 |
|
|
52
|
+
And I save the document 'contractor'
|
|
53
|
+
|
|
54
|
+
Scenario: All
|
|
55
|
+
When I query contacts with find_all
|
|
56
|
+
Then the query result has 3 documents
|
|
57
|
+
|
|
58
|
+
Scenario: Count
|
|
59
|
+
When I query contacts with count
|
|
60
|
+
Then the query result was 3 documents
|
|
61
|
+
|
|
62
|
+
Scenario: First
|
|
63
|
+
When I query contacts with first
|
|
64
|
+
Then the query result is the document 'hashrocket'
|
|
65
|
+
|
|
66
|
+
Scenario: Last
|
|
67
|
+
When I query contacts with last
|
|
68
|
+
Then the query result is the document 'contractor'
|
|
69
|
+
|
|
70
|
+
Scenario: Find One
|
|
71
|
+
When I query contacts to find_one with the id of the 'contractor' document
|
|
72
|
+
Then the query result is the document 'contractor'
|
|
73
|
+
|
|
74
|
+
Scenario: Find One by Param
|
|
75
|
+
When I query contacts to find_one with the to_param of the 'contractor' document
|
|
76
|
+
Then the query result is the document 'contractor'
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Feature: MongoDoc::Base
|
|
2
|
+
|
|
3
|
+
Scenario: creating a simple document
|
|
4
|
+
Given an empty Address document collection
|
|
5
|
+
And a hash named 'hashrocket':
|
|
6
|
+
| Street | City | State | Zip Code |
|
|
7
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
8
|
+
When I create an Address 'address' from the hash 'hashrocket'
|
|
9
|
+
Then 'address' is not a new record
|
|
10
|
+
And the Address collection should have 1 document
|
|
11
|
+
And the document 'address' roundtrips
|
|
12
|
+
|
|
13
|
+
Scenario: saving a simple document
|
|
14
|
+
Given an empty Address document collection
|
|
15
|
+
And an Address document named 'hashrocket' :
|
|
16
|
+
| Street | City | State | Zip Code |
|
|
17
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
18
|
+
When I save the document 'hashrocket'
|
|
19
|
+
Then 'hashrocket' is not a new record
|
|
20
|
+
And the Address collection should have 1 document
|
|
21
|
+
And the document 'hashrocket' roundtrips
|
|
22
|
+
|
|
23
|
+
Scenario: updating an attribute of a simple document
|
|
24
|
+
Given an empty Address document collection
|
|
25
|
+
And an Address document named 'hashrocket' :
|
|
26
|
+
| Street | City | State | Zip Code |
|
|
27
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
28
|
+
And a hash named 'street':
|
|
29
|
+
| Street |
|
|
30
|
+
| 320 First St N |
|
|
31
|
+
And I save the document 'hashrocket'
|
|
32
|
+
When I update the document 'hashrocket' with the hash named 'street'
|
|
33
|
+
And the document 'hashrocket' roundtrips
|
|
34
|
+
Then the attribute 'street' of 'hashrocket' is '320 First St N'
|
|
35
|
+
|
|
36
|
+
Scenario: failing to update an attribute of a simple document
|
|
37
|
+
Given an empty Address document collection
|
|
38
|
+
And an Address document named 'hashrocket' :
|
|
39
|
+
| Street | City | State | Zip Code |
|
|
40
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
41
|
+
And a hash named 'street':
|
|
42
|
+
| Street |
|
|
43
|
+
| 320 First St N |
|
|
44
|
+
And I save the document 'hashrocket'
|
|
45
|
+
And I set the id on the document 'hashrocket' to 1
|
|
46
|
+
When I update the document 'hashrocket' with the hash named 'street'
|
|
47
|
+
Then the last return value is false
|
|
48
|
+
|
|
49
|
+
Scenario: saving a has_many document
|
|
50
|
+
Given an empty Contact document collection
|
|
51
|
+
And a Contact document named 'hashrocket' :
|
|
52
|
+
| Name |
|
|
53
|
+
| Hashrocket |
|
|
54
|
+
And 'hashrocket' has many addresses :
|
|
55
|
+
| Street | City | State | Zip Code |
|
|
56
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
57
|
+
| 1 Main Street | Santiago | Chile | |
|
|
58
|
+
When I save the document 'hashrocket'
|
|
59
|
+
Then 'hashrocket' is not a new record
|
|
60
|
+
And the Contact collection should have 1 document
|
|
61
|
+
And the document 'hashrocket' roundtrips
|
|
62
|
+
|
|
63
|
+
Scenario: saving from a child document
|
|
64
|
+
Given an empty Contact document collection
|
|
65
|
+
And a Contact document named 'hashrocket' :
|
|
66
|
+
| Name |
|
|
67
|
+
| Hashrocket |
|
|
68
|
+
And 'hashrocket' has many addresses :
|
|
69
|
+
| Street | City | State | Zip Code |
|
|
70
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
71
|
+
| 1 Main Street | Santiago | Chile | |
|
|
72
|
+
When I save the last document
|
|
73
|
+
Then 'hashrocket' is not a new record
|
|
74
|
+
And the Contact collection should have 1 document
|
|
75
|
+
And the document 'hashrocket' roundtrips
|
|
76
|
+
|
|
77
|
+
Scenario: Update attributes from a has_many child document
|
|
78
|
+
Given an empty Contact document collection
|
|
79
|
+
And a Contact document named 'hashrocket' :
|
|
80
|
+
| Name |
|
|
81
|
+
| Hashrocket |
|
|
82
|
+
And 'hashrocket' has many addresses :
|
|
83
|
+
| Street | City | State | Zip Code |
|
|
84
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
85
|
+
| 1 Main Street | Santiago | Chile | |
|
|
86
|
+
And I save the last document
|
|
87
|
+
And that @last is named 'chile'
|
|
88
|
+
And a hash named 'street':
|
|
89
|
+
| Street |
|
|
90
|
+
| 1a Calle |
|
|
91
|
+
When I update the document 'chile' with the hash named 'street'
|
|
92
|
+
Then the last return value is true
|
|
93
|
+
And the document 'hashrocket' roundtrips
|
|
94
|
+
|
|
95
|
+
Scenario: update attributes from a has_one child document
|
|
96
|
+
Given an empty Place document collection
|
|
97
|
+
And a Place document named 'hashrocket' :
|
|
98
|
+
| Name |
|
|
99
|
+
| Hashrocket |
|
|
100
|
+
And 'hashrocket' has one Address as address :
|
|
101
|
+
| Street | City | State | Zip Code |
|
|
102
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
|
103
|
+
And I save the last document
|
|
104
|
+
And that @last is named 'address'
|
|
105
|
+
And a hash named 'street':
|
|
106
|
+
| Street | City |
|
|
107
|
+
| 320 1st St. N. | Jax Bch |
|
|
108
|
+
When I update the document 'address' with the hash named 'street'
|
|
109
|
+
Then the Place collection should have 1 document
|
|
110
|
+
And the document 'hashrocket' roundtrips
|
|
111
|
+
|
|
112
|
+
Scenario: Class criteria
|
|
113
|
+
Given an empty Contact document collection
|
|
114
|
+
And a Contact document named 'hashrocket' :
|
|
115
|
+
| Name | Type |
|
|
116
|
+
| Hashrocket | company |
|
|
117
|
+
And I save the last document
|
|
118
|
+
When I query contacts with criteria where('type' => 'company')
|
|
119
|
+
Then the size of the last return value is 1
|
|
120
|
+
|
|
121
|
+
Scenario: Finder
|
|
122
|
+
Given an empty Contact document collection
|
|
123
|
+
And a Contact document named 'hashrocket' :
|
|
124
|
+
| Name | Type |
|
|
125
|
+
| Hashrocket | company |
|
|
126
|
+
And I save the document 'hashrocket'
|
|
127
|
+
When I find a contact using the id of 'hashrocket'
|
|
128
|
+
Then the size of the last return value is 1
|