mongo_thing 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.
data/.bundle/config ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ BUNDLE_WITHOUT: ""
3
+ BUNDLE_PATH: development
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # Use `bundle install` in order to install these gems
2
+ # Use `bundle exec rake` in order to run the specs using the bundle
3
+ source "http://rubygems.org"
4
+
5
+ gem "mongo", "~> 1.0"
6
+ gem "bson", "~> 1.0"
7
+ gem "bson_ext", "~> 1.0"
8
+ gem "activesupport", "3.0.0.beta3"
9
+
10
+ group :development do
11
+ gem "rake"
12
+ gem "ruby-debug"
13
+ gem "rspec", "1.3.0"
14
+ gem "jeweler"
15
+ end
data/MIT_LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Durran Jordan
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/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+
4
+ begin
5
+ Bundler.require(:development)
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "mongo_thing"
8
+ gem.summary = "ODM framework for MongoDB"
9
+ gem.email = "daniel@flyingmachinestudios.com"
10
+ gem.homepage = ""
11
+ gem.authors = ["Daniel Higginbotham"]
12
+
13
+ gem.add_dependency("mongo", "~> 1.0.1")
14
+ gem.add_dependency("bson", "~> 1.0.1")
15
+ end
16
+
17
+ require "spec/rake/spectask"
18
+ Spec::Rake::SpecTask.new(:spec) do |spec|
19
+ spec.pattern = "spec/**/*_spec.rb"
20
+ spec.spec_opts = ["--options", "spec/spec.opts"]
21
+ end
22
+
23
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
24
+ spec.libs << "lib" << "spec"
25
+ spec.pattern = "spec/**/*_spec.rb"
26
+ spec.spec_opts = ["--options", "spec/spec.opts"]
27
+ spec.rcov = true
28
+ end
29
+
30
+ task :default => :spec do
31
+ end
32
+ rescue LoadError => e
33
+ puts "Error loading dependcy: #{e}."
34
+ end
35
+
36
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+ module MongoThing #:nodoc
3
+ class Cursor
4
+ include Enumerable
5
+ # Operations on the Mongo::Cursor object that will not get overriden by the
6
+ # MongoThing::Cursor are defined here.
7
+ OPERATIONS = [
8
+ :admin,
9
+ :close,
10
+ :closed?,
11
+ :count,
12
+ :explain,
13
+ :fields,
14
+ :full_collection_name,
15
+ :hint,
16
+ :limit,
17
+ :order,
18
+ :query_options_hash,
19
+ :query_opts,
20
+ :selector,
21
+ :skip,
22
+ :snapshot,
23
+ :sort,
24
+ :timeout
25
+ ]
26
+
27
+ attr_reader :collection
28
+
29
+ # The operations above will all delegate to the proxied Mongo::Cursor.
30
+ #
31
+ # Example:
32
+ #
33
+ # <tt>cursor.close</tt>
34
+ OPERATIONS.each do |name|
35
+ define_method(name) { |*args| @cursor.send(name, *args) }
36
+ end
37
+
38
+ # Iterate over each document in the cursor and yield to it.
39
+ #
40
+ # Example:
41
+ #
42
+ # <tt>cursor.each { |doc| p doc.title }</tt>
43
+ def each
44
+ @cursor.each do |document|
45
+ yield @klass.new(document)
46
+ end
47
+ end
48
+
49
+ # Create the new +MongoThing::Cursor+.
50
+ #
51
+ # Options:
52
+ #
53
+ # collection: The MongoThing::Collection instance.
54
+ # cursor: The Mongo::Cursor to be proxied.
55
+ #
56
+ # Example:
57
+ #
58
+ # <tt>MongoThing::Cursor.new(Person, cursor)</tt>
59
+ def initialize(klass, cursor)
60
+ @klass, @cursor = klass, cursor
61
+ end
62
+
63
+ # Return the next document in the cursor. Will instantiate a new MongoThing
64
+ # document with the attributes.
65
+ #
66
+ # Example:
67
+ #
68
+ # <tt>cursor.next_document</tt>
69
+ def next_document
70
+ @klass.new(@cursor.next_document)
71
+ end
72
+
73
+ # Returns an array of all the documents in the cursor.
74
+ #
75
+ # Example:
76
+ #
77
+ # <tt>cursor.to_a</tt>
78
+ def to_a
79
+ @cursor.to_a.collect { |attrs| @klass.new(attrs) }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,176 @@
1
+ # encoding: utf-8
2
+ module MongoThing #:nodoc:
3
+ module Document
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ class << self
8
+ attr_accessor :properties
9
+ def properties(*set)
10
+ if !set.empty?
11
+ @properties = set
12
+ else
13
+ @properties | [:_id]
14
+ end
15
+ end
16
+ end
17
+ self.properties = []
18
+
19
+ delegate :db, :collection, :to => "self.class"
20
+ end
21
+
22
+ module ClassMethods
23
+ # Return the database associated with this class.
24
+ def db
25
+ collection.db
26
+ end
27
+
28
+ def collection
29
+ MongoThing.db.collection(self.name)
30
+ end
31
+
32
+ # Finding
33
+ # Returns an array of Document objects
34
+ # Wonder if it would be desirable to expose the cursor?
35
+ def find(selector={}, opts={})
36
+ mongo_cursor = collection.find(selector, opts)
37
+ Cursor.new(self, mongo_cursor).to_a
38
+ end
39
+
40
+ def [](doc_id)
41
+ find_one(doc_id)
42
+ end
43
+
44
+ def find_one(spec_or_object_id=nil, opts={})
45
+ self.new(collection.find_one(spec_or_object_id, opts))
46
+ end
47
+
48
+ # Creating
49
+ def create(document)
50
+ self.new(document).save
51
+ end
52
+
53
+ # Deleting
54
+ def remove(selector={}, opts={})
55
+ collection.remove(selector, opts)
56
+ end
57
+ end
58
+
59
+ module InstanceMethods
60
+ # OpenStruct like behavior
61
+ def method_missing(mid, *args) # :nodoc:
62
+ mname = mid.id2name
63
+ chomped = mname.chomp('=')
64
+ len = args.length
65
+ if self.class.properties.include?(chomped.to_sym)
66
+ if mname == chomped && len > 0 || len > 1
67
+ raise NoMethodError, "undefined method `#{mname}' for #{self}", caller(1)
68
+ end
69
+ new_attribute(mname.chomp('='))
70
+ self.send(mid, *args)
71
+ else
72
+ raise NoMethodError, "undefined method `#{mname}' for #{self}", caller(1)
73
+ end
74
+ end
75
+
76
+ def new_attribute(name)
77
+ name = name.to_sym
78
+ unless self.respond_to?(name)
79
+ class << self; self; end.class_eval do
80
+ define_method(name) { @attributes.send(name) }
81
+ define_method("#{name}=") { |x| @attributes.send("#{name}=".to_sym, x) }
82
+ end
83
+ end
84
+ name
85
+ end
86
+
87
+ # Performs equality checking on the document ids. For more robust
88
+ # equality checking please override this method.
89
+ def ==(other)
90
+ return false unless other.is_a?(Document)
91
+ id == other.id
92
+ end
93
+
94
+ # Delegates to ==
95
+ def eql?(comparison_object)
96
+ self == (comparison_object)
97
+ end
98
+
99
+ def to_hash
100
+ @attributes.to_hash
101
+ end
102
+
103
+ # Clone the current +Document+. This will return all attributes with the
104
+ # exception of the document's id and versions.
105
+ def clone
106
+ self.class.instantiate(@attributes.except("_id").except("versions").dup, true)
107
+ end
108
+
109
+
110
+ # Instantiate a new +Document+, setting the Document's attributes if
111
+ # given. If no attributes are provided, they will be initialized with
112
+ # an empty +Hash+.
113
+ #
114
+ # If a primary key is defined, the document's id will be set to that key,
115
+ # otherwise it will be set to a fresh +BSON::ObjectID+ string.
116
+ #
117
+ # Options:
118
+ #
119
+ # attrs: The attributes +Hash+ to set up the document with.
120
+ def initialize(attrs = {})
121
+ @attributes = NestedOpenStruct.new
122
+ self.attributes = attrs
123
+ @new_record = true if id.nil?
124
+ end
125
+
126
+ def attributes=(attrs={})
127
+ attrs.each do |k,v|
128
+ self.send("#{k}=", v)
129
+ end
130
+ end
131
+
132
+ # Returns the class name plus its attributes.
133
+ def inspect
134
+ attrs = fields.map { |name, field| "#{name}: #{@attributes[name].inspect}" }
135
+ if Mongoid.allow_dynamic_fields
136
+ dynamic_keys = @attributes.keys - fields.keys - ["_id", "_type"]
137
+ attrs += dynamic_keys.map { |name| "#{name}: #{@attributes[name].inspect}" }
138
+ end
139
+ "#<#{self.class.name} _id: #{id}, #{attrs * ', '}>"
140
+ end
141
+
142
+ # Reloads the +Document+ attributes from the database.
143
+ def reload
144
+ if self.id
145
+ self.attributes = self.class[self.id].to_hash
146
+ else
147
+ raise ArgumentError, "this document has not been saved"
148
+ end
149
+ end
150
+
151
+ # Return an array with this +Document+ only in it.
152
+ def to_a
153
+ [ self ]
154
+ end
155
+
156
+ # Returns the id of the Document, used in Rails compatibility.
157
+ def to_param
158
+ id
159
+ end
160
+
161
+ def id
162
+ @attributes._id
163
+ end
164
+
165
+ def id=(new_id)
166
+ @attributes._id = new_id
167
+ end
168
+
169
+ def save
170
+ @attributes._id = BSON::ObjectID.new if @attributes._id.nil?
171
+ collection.save(self.to_hash)
172
+ self
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module NamedScope
4
+ # Creates a named_scope for the +Document+, similar to ActiveRecord's
5
+ # named_scopes. +NamedScopes+ are proxied +Criteria+ objects that can be
6
+ # chained.
7
+ #
8
+ # Example:
9
+ #
10
+ # class Person
11
+ # include Mongoid::Document
12
+ # field :active, :type => Boolean
13
+ # field :count, :type => Integer
14
+ #
15
+ # named_scope :active, :where => { :active => true }
16
+ # named_scope :count_gt_one, :where => { :count.gt => 1 }
17
+ # named_scope :at_least_count, lambda { |count| { :where => { :count.gt => count } } }
18
+ # end
19
+ def named_scope(name, options = {}, &block)
20
+ name = name.to_sym
21
+ scopes[name] = lambda do |parent, *args|
22
+ Scope.new(parent, options.scoped(*args), &block)
23
+ end
24
+ (class << self; self; end).class_eval <<-EOT
25
+ def #{name}(*args)
26
+ scopes[:#{name}].call(self, *args)
27
+ end
28
+ EOT
29
+ end
30
+ alias :scope :named_scope
31
+
32
+ # Return the scopes or default to an empty +Hash+.
33
+ def scopes
34
+ read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ # NestedOpenStruct works like OpenStruct except that all hash values are converted
2
+ # to NestedOpenStruct
3
+
4
+ module MongoThing
5
+ class NestedOpenStruct < OpenStruct
6
+ def initialize(hash=nil)
7
+ @table = {}
8
+ @nested_open_structs = []
9
+ if hash
10
+ for k,v in hash
11
+ v = NestedOpenStruct.new(v) if v.is_a? Hash
12
+ v = v.collect{|nv| nv.is_a?(Hash) ? NestedOpenStruct.new(nv) : nv} if v.is_a?(Array)
13
+ @table[k.to_sym] = v
14
+ new_ostruct_member(k)
15
+ end
16
+ end
17
+ end
18
+
19
+ def method_missing(mid, *args) # :nodoc:
20
+ mname = mid.id2name
21
+ if mname[-1..-1] == "=" && args[0] && args[0].is_a?(Hash)
22
+ args[0] = NestedOpenStruct.new(args[0])
23
+ end
24
+ super
25
+ end
26
+
27
+ def to_hash
28
+ marshal_dump
29
+ end
30
+
31
+ def marshal_dump
32
+ @table.collect do |k,v|
33
+ n = if v.is_a?(NestedOpenStruct)
34
+ v.marshal_dump
35
+ elsif v.is_a?(Array)
36
+ v.collect{|a| a.is_a?(NestedOpenStruct) ? a.marshal_dump : a}
37
+ else
38
+ v
39
+ end
40
+ [k,n]
41
+ end.inject({}){|h,v|h[v[0]] = v[1]; h}
42
+ end
43
+
44
+ def marshal_load(x)
45
+ @table = x
46
+ @table.each_key{|key| new_ostruct_member(key)}
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ module Rails #:nodoc:
2
+ module MongoThing #:nodoc:
3
+ class Railtie < Rails::Railtie #:nodoc:
4
+
5
+ # do we want a custom log subscriber for mongoid?
6
+ # log_subscriber :mongoid, ::Mongoid::Railties::LogSubscriber.new
7
+
8
+ rake_tasks do
9
+ load "mongo-thing/railties/database.rake"
10
+ end
11
+
12
+ # Initialize Mongoid. This will look for a mongoid.yml in the config
13
+ # directory and configure mongoid appropriately.
14
+ #
15
+ # Example mongoid.yml:
16
+ #
17
+ # defaults: &defaults
18
+ # host: localhost
19
+ # slaves:
20
+ # # - host: localhost
21
+ # # port: 27018
22
+ # # - host: localhost
23
+ # # port: 27019
24
+ # allow_dynamic_fields: false
25
+ # parameterize_keys: false
26
+ # persist_in_safe_mode: false
27
+ #
28
+ # development:
29
+ # <<: *defaults
30
+ # database: mongoid
31
+ initializer "setup database" do
32
+ config_file = Rails.root.join("config", "mongoid.yml")
33
+ if config_file.file?
34
+ settings = YAML.load(ERB.new(config_file.read).result)[Rails.env]
35
+ ::MongoThing.connection = settings if settings.present?
36
+ end
37
+ end
38
+
39
+ initializer "verify that mongoid is configured" do
40
+ config.after_initialize do
41
+ begin
42
+ ::Mongoid.master
43
+ rescue ::Mongoid::Errors::InvalidDatabase => e
44
+ unless Rails.root.join("config", "mongoid.yml").file?
45
+ puts "\nMongoid config not found. Create a config file at: config/mongoid.yml"
46
+ puts "to generate one run: script/rails generate mongoid:config\n\n"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ namespace :db do
2
+
3
+ desc 'Drops all the collections for the database for the current Rails.env'
4
+ task :drop => :environment do
5
+ Mongoid.master.collections.each{|col| col.drop unless col.name == 'system.users' }
6
+ end
7
+
8
+ desc 'Load the seed data from db/seeds.rb'
9
+ task :seed => :environment do
10
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb')
11
+ load(seed_file) if File.exist?(seed_file)
12
+ end
13
+
14
+ desc 'Create the database, and initialize with the seed data'
15
+ task :setup => [ 'db:create', 'db:seed' ]
16
+
17
+ desc 'Delete data and seed'
18
+ task :reseed => [ 'db:drop', 'db:seed' ]
19
+
20
+ task :create => :environment do
21
+ # noop
22
+ end
23
+
24
+ task :migrate => :environment do
25
+ # noop
26
+ end
27
+
28
+ namespace :schema do
29
+ task :load do
30
+ # noop
31
+ end
32
+ end
33
+
34
+ ########
35
+ # TODO: lots more useful db tasks can be added here. stuff like copyDatabase, etc
36
+ ########
37
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ # Copyright (c) 2010 Daniel Higginbotham
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'rubygems'
24
+ require 'bundler'
25
+ Bundler.setup(:default)
26
+ require 'active_support/core_ext'
27
+ require 'bson'
28
+ require 'ostruct'
29
+
30
+ $:.unshift(File.expand_path(File.dirname(__FILE__)))
31
+ require 'mongo_thing/cursor'
32
+ require 'mongo_thing/document'
33
+ require 'mongo_thing/nested_ostruct'
34
+
35
+
36
+ module MongoThing #:nodoc
37
+
38
+ class << self
39
+ attr_accessor :connection, :db
40
+ def connection=(conn)
41
+ case conn
42
+ when Hash
43
+ @connection = Mongo::Connection.new(conn.delete(:host), conn.delete(:port), conn)
44
+ when Mongo::Connection
45
+ @connection = conn
46
+ end
47
+ self.db = conn if conn[:name]
48
+ end
49
+
50
+ def db=(new_db)
51
+ case new_db
52
+ when String, Symbol
53
+ @db = connection.db(new_db.to_s)
54
+ when Hash
55
+ @db = connection.db(new_db[:name], new_db)
56
+ when Mongo::DB
57
+ @db = new_db
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+
64
+ end
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{mongo_thing}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Daniel Higginbotham"]
12
+ s.date = %q{2010-05-09}
13
+ s.email = %q{daniel@flyingmachinestudios.com}
14
+ s.files = [
15
+ ".bundle/config",
16
+ ".gitignore",
17
+ "Gemfile",
18
+ "MIT_LICENSE",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "lib/mongo_thing.rb",
22
+ "lib/mongo_thing/cursor.rb",
23
+ "lib/mongo_thing/document.rb",
24
+ "lib/mongo_thing/named_scope.rb",
25
+ "lib/mongo_thing/nested_ostruct.rb",
26
+ "lib/mongo_thing/railtie.rb",
27
+ "lib/mongo_thing/railties/database.rake",
28
+ "mongo_thing.gemspec",
29
+ "spec/config/mongoid.yml",
30
+ "spec/integration/mongo_thing/document_spec.rb",
31
+ "spec/integration/mongo_thing/nested_ostruct_spec.rb",
32
+ "spec/integration/mongo_thing_spec.rb",
33
+ "spec/spec.opts",
34
+ "spec/spec_helper.rb"
35
+ ]
36
+ s.homepage = %q{}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.6}
40
+ s.summary = %q{ODM framework for MongoDB}
41
+ s.test_files = [
42
+ "spec/integration/mongo_thing/document_spec.rb",
43
+ "spec/integration/mongo_thing/nested_ostruct_spec.rb",
44
+ "spec/integration/mongo_thing_spec.rb",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<mongo>, ["~> 1.0.1"])
54
+ s.add_runtime_dependency(%q<bson>, ["~> 1.0.1"])
55
+ else
56
+ s.add_dependency(%q<mongo>, ["~> 1.0.1"])
57
+ s.add_dependency(%q<bson>, ["~> 1.0.1"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<mongo>, ["~> 1.0.1"])
61
+ s.add_dependency(%q<bson>, ["~> 1.0.1"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,19 @@
1
+ :defaults: &defaults
2
+ :host: localhost
3
+ :slaves:
4
+ # - host: localhost
5
+ # port: 27018
6
+ # - host: localhost
7
+ # port: 27019
8
+ :allow_dynamic_fields: false
9
+ :parameterize_keys: false
10
+ :persist_in_safe_mode: false
11
+ :raise_not_found_error: false
12
+ :reconnect_time: 5
13
+ :use_object_ids: true
14
+ :persist_types: false
15
+ :option_no_exist: false
16
+
17
+ :test:
18
+ <<: *defaults
19
+ :name: mongo_thing_test
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ class Person
4
+ include MongoThing::Document
5
+ self.properties = [:name, :address, :friends]
6
+ end
7
+
8
+
9
+ describe MongoThing::Document do
10
+ describe "attributes" do
11
+ it "should only allow properties to be treated as attributes" do
12
+ p = Person.new
13
+ lambda{p.blarg = "Tom"}.should raise_error(NoMethodError)
14
+ end
15
+
16
+ it "should allow properties to be treated as attributes" do
17
+ p = Person.new
18
+ lambda{p.name = "Tom"}.should_not raise_error(NoMethodError)
19
+ end
20
+
21
+ it "should assign attributes in the initializer" do
22
+ p = Person.new({
23
+ :name => "Tom"
24
+ })
25
+ p.name.should == "Tom"
26
+ end
27
+
28
+ it "should raise an error when trying to assign a non-attribute in the initializer" do
29
+ lambda {
30
+ p = Person.new({
31
+ :name => "Tom",
32
+ :foo => "bar"
33
+ })
34
+ }.should raise_error(NoMethodError)
35
+ end
36
+
37
+ it "should return a hash of attributes" do
38
+ person_hash = {
39
+ :name => "Tom",
40
+ :address => {:street => "Tomahawk", :city => "Placeville"},
41
+ :friends => [
42
+ {:name => "John", :address => {:street => "Pleasant", :city => "Cityville"}},
43
+ {:name => "Bill", :address => {:street => "Prospect", :city => "Townville"}}
44
+ ]
45
+ }
46
+
47
+ p = Person.new(person_hash)
48
+ p.to_hash.should == person_hash
49
+ end
50
+
51
+ it "should set properties using properties method" do
52
+ class SetProperties
53
+ include MongoThing::Document
54
+ properties :one, :two, :three
55
+ end
56
+
57
+ lambda{SetProperties.new(:one => 1, :two => 2, :three => 3)}.should_not raise_error
58
+ end
59
+ end
60
+
61
+ describe "class modifications" do
62
+ it "should add the 'properties' attribute to class" do
63
+ Person.respond_to?(:properties).should be_true
64
+ end
65
+
66
+ it "should default 'properties' to [:_id]" do
67
+ class Bear
68
+ include MongoThing::Document
69
+ end
70
+
71
+ Bear.properties.should == [:_id]
72
+ end
73
+ end
74
+
75
+ describe "actual db interaction" do
76
+ before(:all) do
77
+ connect_to_test_database
78
+ end
79
+ describe "saving" do
80
+ it "should save a basic document" do
81
+ p = Person.new
82
+ p.name = "Tom"
83
+ p.save
84
+ end
85
+
86
+ it "should not have an ID before being saved" do
87
+ p = Person.new
88
+ p.id.should be_nil
89
+ end
90
+
91
+ it "should have an ID after being saved" do
92
+ p = Person.new
93
+ p.name = "Tom"
94
+ p.save
95
+ p.id.should_not be_nil
96
+ end
97
+
98
+ it "should save a document with 'create'" do
99
+ Person.create(:name => "Tom").id.should_not be_nil
100
+ end
101
+ end
102
+
103
+ describe "finding" do
104
+ it "should find a person given an ID" do
105
+ p = Person.new
106
+ p.name = "Tom"
107
+ p.save
108
+
109
+ h = Person[p.id]
110
+ h.name.should == "Tom"
111
+ h.id.should == p.id
112
+
113
+ i = Person.find_one(p.id)
114
+ i.name.should == "Tom"
115
+ i.id.should == p.id
116
+ end
117
+
118
+ it "should return all matching documents" do
119
+ Person.create(:name => "Tom")
120
+ Person.create(:name => "Voldemort")
121
+
122
+ r = Person.find.to_a
123
+ end
124
+
125
+ it "should initialize documents from find" do
126
+ Person.create(:name => "Tom")
127
+ Person.create(:name => "Voldemort")
128
+
129
+ r = Person.find.to_a
130
+ r[0].name.should == "Tom"
131
+ r[1].name.should == "Voldemort"
132
+ end
133
+
134
+ it "should reload a document" do
135
+ p = Person.create(:name => "Tom")
136
+
137
+ p.name = "Voldemort"
138
+ p.reload
139
+ p.name.should == "Tom"
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe MongoThing::NestedOpenStruct do
4
+ before(:each) do
5
+ @person_hash = {
6
+ :name => "Tom",
7
+ :address => {:street => "Tomahawk", :city => "Placeville"},
8
+ :friends => [
9
+ {:name => "John", :address => {:street => "Pleasant", :city => "Cityville"}},
10
+ {:name => "Bill", :address => {:street => "Prospect", :city => "Townville"}}
11
+ ]
12
+ }
13
+ end
14
+
15
+ it "should not modify original hash" do
16
+ MongoThing::NestedOpenStruct.new(@person_hash)
17
+
18
+ @person_hash.should == {
19
+ :name => "Tom",
20
+ :address => {:street => "Tomahawk", :city => "Placeville"},
21
+ :friends => [
22
+ {:name => "John", :address => {:street => "Pleasant", :city => "Cityville"}},
23
+ {:name => "Bill", :address => {:street => "Prospect", :city => "Townville"}}
24
+ ]
25
+ }
26
+ end
27
+
28
+ it "should convert a hash value to a nested open struct" do
29
+ p = MongoThing::NestedOpenStruct.new(@person_hash)
30
+
31
+ p.name.should == "Tom"
32
+ p.address.street.should == "Tomahawk"
33
+ p.address.city.should == "Placeville"
34
+ p.friends.size.should == 2
35
+ p.friends[0].name.should == "John"
36
+ p.friends[0].address.street.should == "Pleasant"
37
+ p.friends[0].address.city.should == "Cityville"
38
+ end
39
+
40
+ it "should convert NestedOpenStruct values to hashes when dumping" do
41
+ p = MongoThing::NestedOpenStruct.new(@person_hash)
42
+ p.marshal_dump.should == @person_hash
43
+ end
44
+
45
+ it "should respond identically to marshal_dump and to_hash" do
46
+ p = MongoThing::NestedOpenStruct.new(@person_hash)
47
+ p.marshal_dump.should == p.to_hash
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ # Connection is established in spec_helper
4
+ describe MongoThing do
5
+ describe "connection" do
6
+ it "should set the connection given a hash" do
7
+ MongoThing.connection.host.should == "localhost"
8
+ MongoThing.connection.size.should == 1
9
+ end
10
+
11
+ it "should set the database when a name is given in connection settings" do
12
+ MongoThing.db.should be_a Mongo::DB
13
+ end
14
+ end
15
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format progress
3
+ --backtrace
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require(:default, :development)
4
+ require "mongo_thing"
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
8
+
9
+ MODELS = File.join(File.dirname(__FILE__), "models")
10
+ $LOAD_PATH.unshift(MODELS)
11
+
12
+
13
+ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
14
+
15
+ Spec::Runner.configure do |config|
16
+ config.before :suite do
17
+ connect_to_test_database
18
+ end
19
+
20
+ config.after(:each) do
21
+ MongoThing.db.collections.each(&:remove)
22
+ end
23
+
24
+ config.after :suite do
25
+ MongoThing.db.collections.each(&:drop)
26
+ end
27
+ end
28
+
29
+ # This is probably a very naive way to do thsi
30
+ def connect_to_test_database
31
+ config = File.read(File.join(File.dirname(__FILE__), 'config', 'mongoid.yml'))
32
+ settings = YAML.load(ERB.new(config).result)
33
+ MongoThing.connection = settings[:test] unless MongoThing.connection
34
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongo_thing
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Daniel Higginbotham
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-09 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ type: :runtime
22
+ name: mongo
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ - 1
31
+ version: 1.0.1
32
+ requirement: *id001
33
+ prerelease: false
34
+ - !ruby/object:Gem::Dependency
35
+ type: :runtime
36
+ name: bson
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 0
44
+ - 1
45
+ version: 1.0.1
46
+ requirement: *id002
47
+ prerelease: false
48
+ description:
49
+ email: daniel@flyingmachinestudios.com
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - .bundle/config
58
+ - .gitignore
59
+ - Gemfile
60
+ - MIT_LICENSE
61
+ - Rakefile
62
+ - VERSION
63
+ - lib/mongo_thing.rb
64
+ - lib/mongo_thing/cursor.rb
65
+ - lib/mongo_thing/document.rb
66
+ - lib/mongo_thing/named_scope.rb
67
+ - lib/mongo_thing/nested_ostruct.rb
68
+ - lib/mongo_thing/railtie.rb
69
+ - lib/mongo_thing/railties/database.rake
70
+ - mongo_thing.gemspec
71
+ - spec/config/mongoid.yml
72
+ - spec/integration/mongo_thing/document_spec.rb
73
+ - spec/integration/mongo_thing/nested_ostruct_spec.rb
74
+ - spec/integration/mongo_thing_spec.rb
75
+ - spec/spec.opts
76
+ - spec/spec_helper.rb
77
+ has_rdoc: true
78
+ homepage: ""
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options:
83
+ - --charset=UTF-8
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project:
103
+ rubygems_version: 1.3.6
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: ODM framework for MongoDB
107
+ test_files:
108
+ - spec/integration/mongo_thing/document_spec.rb
109
+ - spec/integration/mongo_thing/nested_ostruct_spec.rb
110
+ - spec/integration/mongo_thing_spec.rb
111
+ - spec/spec_helper.rb