mongodoc 0.0.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.
Files changed (56) hide show
  1. data/.document +5 -0
  2. data/.gitignore +7 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +80 -0
  6. data/VERSION +1 -0
  7. data/data/.gitignore +2 -0
  8. data/features/mongodoc_base.feature +117 -0
  9. data/features/saving_an_object.feature +17 -0
  10. data/features/step_definitions/collection_steps.rb +14 -0
  11. data/features/step_definitions/connect_steps.rb +4 -0
  12. data/features/step_definitions/document_steps.rb +88 -0
  13. data/features/step_definitions/json_steps.rb +9 -0
  14. data/features/step_definitions/object_steps.rb +43 -0
  15. data/features/step_definitions/util_steps.rb +7 -0
  16. data/features/support/support.rb +9 -0
  17. data/lib/mongodoc.rb +17 -0
  18. data/lib/mongodoc/attributes.rb +97 -0
  19. data/lib/mongodoc/base.rb +163 -0
  20. data/lib/mongodoc/bson.rb +45 -0
  21. data/lib/mongodoc/connection.rb +20 -0
  22. data/lib/mongodoc/ext/array.rb +5 -0
  23. data/lib/mongodoc/ext/binary.rb +7 -0
  24. data/lib/mongodoc/ext/boolean_class.rb +11 -0
  25. data/lib/mongodoc/ext/date.rb +16 -0
  26. data/lib/mongodoc/ext/date_time.rb +13 -0
  27. data/lib/mongodoc/ext/dbref.rb +7 -0
  28. data/lib/mongodoc/ext/hash.rb +7 -0
  29. data/lib/mongodoc/ext/nil_class.rb +5 -0
  30. data/lib/mongodoc/ext/numeric.rb +17 -0
  31. data/lib/mongodoc/ext/object.rb +17 -0
  32. data/lib/mongodoc/ext/object_id.rb +7 -0
  33. data/lib/mongodoc/ext/regexp.rb +5 -0
  34. data/lib/mongodoc/ext/string.rb +5 -0
  35. data/lib/mongodoc/ext/symbol.rb +5 -0
  36. data/lib/mongodoc/ext/time.rb +5 -0
  37. data/lib/mongodoc/parent_proxy.rb +37 -0
  38. data/lib/mongodoc/proxy.rb +76 -0
  39. data/lib/mongodoc/query.rb +7 -0
  40. data/lib/mongodoc/value_equals.rb +8 -0
  41. data/mongod.example.yml +2 -0
  42. data/mongodoc.gemspec +117 -0
  43. data/script/console +8 -0
  44. data/spec/attributes_spec.rb +159 -0
  45. data/spec/base_ext.rb +9 -0
  46. data/spec/base_spec.rb +273 -0
  47. data/spec/bson_matchers.rb +54 -0
  48. data/spec/bson_spec.rb +316 -0
  49. data/spec/connection_spec.rb +81 -0
  50. data/spec/parent_proxy_spec.rb +42 -0
  51. data/spec/query_spec.rb +12 -0
  52. data/spec/spec.opts +2 -0
  53. data/spec/spec_helper.rb +13 -0
  54. data/spec/test_classes.rb +19 -0
  55. data/spec/test_documents.rb +35 -0
  56. metadata +159 -0
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,7 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ mongod.yml
7
+ nohup.out
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.
@@ -0,0 +1,18 @@
1
+ = mongodoc
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
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 Les Hill. See LICENSE for details.
@@ -0,0 +1,80 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "mongodoc"
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.16"
14
+ gem.add_dependency "durran-validatable", "= 1.8.2"
15
+ gem.add_development_dependency "rspec"
16
+ gem.add_development_dependency "cucumber"
17
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
+ end
19
+ Jeweler::GemcutterTasks.new
20
+ rescue LoadError
21
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
22
+ end
23
+
24
+ require 'cucumber/rake/task'
25
+ Cucumber::Rake::Task.new(:features) do |t|
26
+ t.cucumber_opts = "--format pretty --tag ~@wip"
27
+ end
28
+
29
+ namespace :cucumber do
30
+ Cucumber::Rake::Task.new(:wip) do |t|
31
+ t.cucumber_opts = "--format pretty --tag @wip"
32
+ end
33
+ end
34
+
35
+ require 'spec/rake/spectask'
36
+ Spec::Rake::SpecTask.new(:spec) do |spec|
37
+ spec.spec_opts = ['--options', "#{File.expand_path(File.dirname(__FILE__))}/spec/spec.opts"]
38
+ spec.libs << 'lib' << 'spec'
39
+ spec.spec_files = FileList['spec/**/*_spec.rb']
40
+ end
41
+
42
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
43
+ spec.spec_opts = ['--options', "#{File.expand_path(File.dirname(__FILE__))}/spec/spec.opts"]
44
+ spec.libs << 'lib' << 'spec'
45
+ spec.pattern = 'spec/**/*_spec.rb'
46
+ spec.rcov = true
47
+ end
48
+
49
+ task :spec => :check_dependencies
50
+
51
+ task :default => :spec
52
+
53
+ require 'rake/rdoctask'
54
+ Rake::RDocTask.new do |rdoc|
55
+ if File.exist?('VERSION')
56
+ version = File.read('VERSION')
57
+ else
58
+ version = ""
59
+ end
60
+
61
+ rdoc.rdoc_dir = 'rdoc'
62
+ rdoc.title = "mongodoc #{version}"
63
+ rdoc.rdoc_files.include('README*')
64
+ rdoc.rdoc_files.include('lib/**/*.rb')
65
+ end
66
+
67
+ namespace :mongo do
68
+ desc 'Start mongod'
69
+ task :start do
70
+ default_config = { "dbpath" => "/data/db" }
71
+ config = begin
72
+ YAML.load_file(File.join(File.dirname(__FILE__), 'mongod.yml'))
73
+ rescue Exception => e
74
+ {}
75
+ end
76
+ config = default_config.merge(config)
77
+ sh("nohup #{config['mongod'] || 'mongod'} --dbpath #{config['dbpath']} &")
78
+ puts "\n"
79
+ end
80
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,2 @@
1
+ *
2
+ !.gitignore
@@ -0,0 +1,117 @@
1
+ Feature: MongoDoc::Base
2
+
3
+ Scenario: creating a simple document
4
+ Given a valid connection to the 'test' database
5
+ And an empty Address document collection
6
+ And a hash named 'hashrocket':
7
+ | Street | City | State | Zip Code |
8
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
9
+ When I create an Address 'address' from the hash 'hashrocket'
10
+ Then 'address' is not a new record
11
+ And the Address collection should have 1 document
12
+ And the document 'address' roundtrips
13
+
14
+ Scenario: saving a simple document
15
+ Given a valid connection to the 'test' database
16
+ And an empty Address document collection
17
+ And an Address document named 'hashrocket' :
18
+ | Street | City | State | Zip Code |
19
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
20
+ When I save the document 'hashrocket'
21
+ Then 'hashrocket' is not a new record
22
+ And the Address collection should have 1 document
23
+ And the document 'hashrocket' roundtrips
24
+
25
+ Scenario: updating an attribute of a simple document
26
+ Given a valid connection to the 'test' database
27
+ And an empty Address document collection
28
+ And an Address document named 'hashrocket' :
29
+ | Street | City | State | Zip Code |
30
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
31
+ And a hash named 'street':
32
+ | Street |
33
+ | 320 First St N |
34
+ And I save the document 'hashrocket'
35
+ When I update the document 'hashrocket' with the hash named 'street'
36
+ And the document 'hashrocket' roundtrips
37
+ Then the attribute 'street' of 'hashrocket' is '320 First St N'
38
+
39
+ Scenario: failing to update an attribute of a simple document
40
+ Given a valid connection to the 'test' database
41
+ And an empty Address document collection
42
+ And an Address document named 'hashrocket' :
43
+ | Street | City | State | Zip Code |
44
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
45
+ And a hash named 'street':
46
+ | Street |
47
+ | 320 First St N |
48
+ And I save the document 'hashrocket'
49
+ And I set the id on the document 'hashrocket' to 1
50
+ When I update the document 'hashrocket' with the hash named 'street'
51
+ Then the last return value is false
52
+
53
+ Scenario: saving a has_many document
54
+ Given a valid connection to the 'test' database
55
+ And an empty Contact document collection
56
+ And a Contact document named 'hashrocket' :
57
+ | Name |
58
+ | Hashrocket |
59
+ And 'hashrocket' has many addresses :
60
+ | Street | City | State | Zip Code |
61
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
62
+ | 1 Main Street | Santiago | Chile | |
63
+ When I save the document 'hashrocket'
64
+ Then 'hashrocket' is not a new record
65
+ And the Contact collection should have 1 document
66
+ And the document 'hashrocket' roundtrips
67
+
68
+ Scenario: saving from a child document
69
+ Given a valid connection to the 'test' database
70
+ And an empty Contact document collection
71
+ And a Contact document named 'hashrocket' :
72
+ | Name |
73
+ | Hashrocket |
74
+ And 'hashrocket' has many addresses :
75
+ | Street | City | State | Zip Code |
76
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
77
+ | 1 Main Street | Santiago | Chile | |
78
+ When I save the last document
79
+ Then 'hashrocket' is not a new record
80
+ And the Contact collection should have 1 document
81
+ And the document 'hashrocket' roundtrips
82
+
83
+ Scenario: failing to update attributes from a has_many child document
84
+ Given a valid connection to the 'test' database
85
+ And an empty Contact document collection
86
+ And a Contact document named 'hashrocket' :
87
+ | Name |
88
+ | Hashrocket |
89
+ And 'hashrocket' has many addresses :
90
+ | Street | City | State | Zip Code |
91
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
92
+ | 1 Main Street | Santiago | Chile | |
93
+ And I save the last document
94
+ And that @last is named 'chile'
95
+ And a hash named 'street':
96
+ | Street |
97
+ | 1a Calle |
98
+ When I update the document 'chile' with the hash named 'street'
99
+ Then the last return value is false
100
+
101
+ Scenario: update attributes from a has_one child document
102
+ Given a valid connection to the 'test' database
103
+ And an empty Place document collection
104
+ And a Place document named 'hashrocket' :
105
+ | Name |
106
+ | Hashrocket |
107
+ And 'hashrocket' has one Address as address :
108
+ | Street | City | State | Zip Code |
109
+ | 320 First Street North | Jacksonville Beach | FL | 32250 |
110
+ And I save the last document
111
+ And that @last is named 'address'
112
+ And a hash named 'street':
113
+ | Street | City |
114
+ | 320 1st St. N. | Jax Bch |
115
+ When I update the document 'address' with the hash named 'street'
116
+ Then the Place collection should have 1 document
117
+ And the document 'hashrocket' roundtrips
@@ -0,0 +1,17 @@
1
+ Feature: saving an object
2
+
3
+ Scenario: saving simple json
4
+ Given a valid connection to the 'test' database
5
+ And a new collection named 'test'
6
+ When I save the json '{"name":"name"}'
7
+ Then the collection should have 1 document
8
+ And the json '{"name":"name"}' roundtrips
9
+
10
+ Scenario: saving a ruby object
11
+ Given a valid connection to the 'test' database
12
+ And a new collection named 'test'
13
+ And an object 'movie'
14
+ When I save the object 'movie'
15
+ Then the collection should have 1 document
16
+ And the object 'movie' roundtrips
17
+
@@ -0,0 +1,14 @@
1
+ Given /a new collection named '(.*)'/ do |name|
2
+ @db.drop_collection(name)
3
+ @collection = @db.collection(name)
4
+ end
5
+
6
+ Given /^an empty (\w+) collection$/ do |name|
7
+ @db.drop_collection(name)
8
+ @db.create_collection(name, :strict => true)
9
+ end
10
+
11
+ Then /the collection should have (\d+) documents?/ do |count|
12
+ @collection.count.should == count.to_i
13
+ end
14
+
@@ -0,0 +1,4 @@
1
+ Given /a valid connection to the '(.*)' database/ do |db|
2
+ MongoDoc.connect
3
+ @db = MongoDoc.database(db)
4
+ end
@@ -0,0 +1,88 @@
1
+ Given /^an empty (\w+) document collection$/ do |doc|
2
+ klass = doc.constantize
3
+ Given "an empty #{klass.collection_name} collection"
4
+ end
5
+
6
+ Given /^an? (\w+) document named '(.*)' :$/ do |doc, name, table|
7
+ @all = []
8
+ klass = doc.constantize
9
+ table.hashes.each do |hash|
10
+ @last = klass.new
11
+ hash.each do |attr, value|
12
+ @last.send("#{attr.underscore.gsub(' ', '_')}=", value)
13
+ end
14
+ @all << @last
15
+ end
16
+ instance_variable_set("@#{name}", @last)
17
+ end
18
+
19
+ Given /^'(.*)' has one (.*?) as (.*) :$/ do |doc_name, class_name, assoc_name, table|
20
+ doc = instance_variable_get("@#{doc_name}")
21
+ obj = class_name.constantize.new
22
+ table.hashes.each do |hash|
23
+ hash.each do |key, value|
24
+ obj.send("#{key.underscore.gsub(' ', '_')}=", value)
25
+ end
26
+ end
27
+ doc.send("#{assoc_name.underscore.gsub(' ', '_')}=", obj)
28
+ @last = obj
29
+ end
30
+
31
+ Given /^'(.*)' has (?:a|an|many) (.*) :$/ do |doc_name, assoc_name, table|
32
+ doc = instance_variable_get("@#{doc_name}")
33
+ table.hashes.each do |hash|
34
+ doc.send(assoc_name) << hash.inject({}) do |attrs, (attr, value)|
35
+ attrs["#{attr.underscore.gsub(' ', '_')}"] = value
36
+ attrs
37
+ end
38
+ end
39
+ @all = doc.send(assoc_name)
40
+ @last = @all.last
41
+ end
42
+
43
+ Given /^I set the id on the document '(.*)' to (.*)$/ do |doc_name, value|
44
+ doc = instance_variable_get("@#{doc_name}")
45
+ doc._id = Mongo::ObjectID.new([value.to_i])
46
+ end
47
+
48
+ When /^I save the document '(.*)'$/ do |name|
49
+ object = instance_variable_get("@#{name}")
50
+ @last_return = object.save
51
+ end
52
+
53
+ When /^I save the last document$/ do
54
+ @last_return = @last.save
55
+ end
56
+
57
+ When /^I create an (.*) '(.*)' from the hash '(.*)'$/ do |doc, name, hash|
58
+ klass = doc.constantize
59
+ attrs = instance_variable_get("@#{hash}")
60
+ instance_variable_set("@#{name}", klass.create(attrs))
61
+ end
62
+
63
+ When /^I update the document '(.*)' with the hash named '(.*)'$/ do |doc_name, hash_name|
64
+ doc = instance_variable_get("@#{doc_name}")
65
+ attrs = instance_variable_get("@#{hash_name}")
66
+ @last_return = doc.update_attributes(attrs)
67
+ end
68
+
69
+ Then /^'(.*)' is not a new record$/ do |name|
70
+ instance_variable_get("@#{name}").new_record?.should be_false
71
+ end
72
+
73
+ Then /the (.*) collection should have (\d+) documents?/ do |doc, count|
74
+ klass = doc.constantize
75
+ klass.count.should == count.to_i
76
+ end
77
+
78
+ Then /^the document '(.*)' roundtrips$/ do |name|
79
+ object = instance_variable_get("@#{name}")
80
+ from_db = object.class.find_one(object._id)
81
+ from_db.should == object
82
+ instance_variable_set("@#{name}", from_db)
83
+ end
84
+
85
+ Then /^the last return value is false$/ do
86
+ @last_return.should be_false
87
+ end
88
+
@@ -0,0 +1,9 @@
1
+ When /^I save the json '(\{.*\})'$/ do |json_text|
2
+ bson = JSON.parse(json_text).to_bson
3
+ @last_save = @collection.save(bson)
4
+ end
5
+
6
+ Then /^the json '(\{.*\})' roundtrips$/ do |json_text|
7
+ bson = JSON.parse(json_text).to_bson
8
+ MongoDoc::BSON.decode(@collection.find_one(@last_save)).should be_mongo_eql(bson, false)
9
+ end
@@ -0,0 +1,43 @@
1
+ Given /^an object '(.*)'$/ do |name|
2
+ @movie = Movie.new
3
+ @movie.title = 'Gone with the Wind'
4
+ @movie.director = 'Victor Fleming'
5
+ @movie.writers = ['Sidney Howard']
6
+ @director = Director.new
7
+ @director.name = 'Victor Fleming'
8
+ @award = AcademyAward.new
9
+ @award.year = '1940'
10
+ @award.category = 'Best Director'
11
+ @director.awards = [@award]
12
+ @movie.director = @director
13
+ end
14
+
15
+ Given /^a hash named '(.*)':$/ do |name, table|
16
+ @all = []
17
+ table.hashes.each do |hash|
18
+ @last = hash.inject({}) do |h, (key, value)|
19
+ h["#{key.underscore.gsub(' ', '_')}"] = value
20
+ h
21
+ end
22
+ @all << @last
23
+ end
24
+ instance_variable_set("@#{name}", @last)
25
+
26
+ end
27
+
28
+ When /^I save the object '(.*)'$/ do |name|
29
+ object = instance_variable_get("@#{name}")
30
+ @last_save = @collection.save(object.to_bson)
31
+ end
32
+
33
+ Then /^the object '(.*)' roundtrips$/ do |name|
34
+ object = instance_variable_get("@#{name}")
35
+ object.instance_variable_set("@_id", @last_save)
36
+ MongoDoc::BSON.decode(@collection.find_one(@last_save)).should == object
37
+ end
38
+
39
+ Then /^the attribute '(.*)' of '(.*)' is '(.*)'$/ do |attr, var, value|
40
+ object = instance_variable_get("@#{var}")
41
+ object.send(attr).to_s.should == value
42
+ end
43
+
@@ -0,0 +1,7 @@
1
+ Given /^that @last is named '(.*)'$/ do |name|
2
+ instance_variable_set("@#{name}", @last)
3
+ end
4
+
5
+ Then /^I invoke the debugger$/ do
6
+ require 'ruby-debug'; Debugger.start; Debugger.settings[:autoeval] = 1; Debugger.settings[:autolist] = 1; debugger
7
+ end