mongomodel 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://gemcutter.org"
2
+ git "git://github.com/rails/rails.git"
3
+
4
+ gem "activemodel"
5
+ gem "activesupport"
6
+
7
+ gem "mongo"
8
+ gem "bson"
9
+ gem "bson_ext"
10
+
11
+ gem "rspec"
data/Rakefile CHANGED
@@ -36,9 +36,10 @@ begin
36
36
  gem.authors = ["Sam Pohlenz"]
37
37
  gem.version = MongoModel::VERSION
38
38
 
39
- gem.add_dependency('activesupport', '>= 3.0.pre')
40
- gem.add_dependency('activemodel', '>= 3.0.pre')
41
- gem.add_dependency('mongo', '>= 0.18.3')
39
+ gem.add_dependency('activesupport', '>= 3.0.0.beta3')
40
+ gem.add_dependency('activemodel', '>= 3.0.0.beta3')
41
+ gem.add_dependency('mongo', '>= 0.20.1')
42
+ gem.add_dependency('bson', '>= 0.20.1')
42
43
  end
43
44
 
44
45
  Jeweler::GemcutterTasks.new
@@ -2,6 +2,16 @@
2
2
 
3
3
  puts "Loading MongoModel sandbox..."
4
4
 
5
+ begin
6
+ # Try to require the preresolved locked set of gems.
7
+ require File.expand_path('../../.bundle/environment', __FILE__)
8
+ rescue LoadError
9
+ # Fall back on doing an unlocked resolve at runtime.
10
+ require "rubygems"
11
+ require "bundler"
12
+ Bundler.setup
13
+ end
14
+
5
15
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
6
16
 
7
17
  require 'irb'
@@ -4,6 +4,10 @@ module MongoModel
4
4
 
5
5
  include ActiveModel::Conversion
6
6
 
7
+ def persisted?
8
+ !new_record?
9
+ end
10
+
7
11
  module ClassMethods
8
12
  include ActiveModel::Naming
9
13
  end
@@ -37,6 +37,10 @@ module MongoModel
37
37
  def polymorphic?
38
38
  options[:polymorphic]
39
39
  end
40
+
41
+ def scope_options
42
+ options.slice(:conditions, :select, :offset, :limit, :order)
43
+ end
40
44
 
41
45
  def self.properties(&block)
42
46
  block_given? ? write_inheritable_attribute(:properties, block) : read_inheritable_attribute(:properties)
@@ -47,7 +47,7 @@ module MongoModel
47
47
  end
48
48
 
49
49
  def load_target
50
- @target = @association.find_target unless loaded?
50
+ @target = association.find_target unless loaded?
51
51
  loaded!
52
52
  rescue MongoModel::DocumentNotFound
53
53
  reset
@@ -16,10 +16,12 @@ module MongoModel
16
16
 
17
17
  methods do |association|
18
18
  define_method(association.name) do |*args|
19
- force_reload = args.first || false
19
+ force_reload = args.first unless args.empty?
20
20
 
21
- associations[association.name].proxy.reset if force_reload
22
- associations[association.name].proxy
21
+ proxy = associations[association.name].proxy
22
+
23
+ proxy.reset if force_reload
24
+ proxy.target.nil? ? nil : proxy
23
25
  end
24
26
 
25
27
  define_method("#{association.name}=") { |obj| associations[association.name].replace(obj) }
@@ -51,16 +53,16 @@ module MongoModel
51
53
  end
52
54
 
53
55
  def replace(obj)
54
- ensure_class(obj) unless polymorphic?
56
+ ensure_class(obj) if obj && !polymorphic?
55
57
 
56
- instance[foreign_key] = obj.id
57
- instance[type_key] = obj.class if polymorphic?
58
+ instance[foreign_key] = obj ? obj.id : nil
59
+ instance[type_key] = obj ? obj.class : nil if polymorphic?
58
60
 
59
61
  super
60
62
  end
61
63
 
62
64
  def find_target
63
- target_class.find(target_id) unless target_id.nil? || target_class.nil?
65
+ target_class.find(target_id) if target_id && target_class
64
66
  end
65
67
  end
66
68
  end
@@ -23,7 +23,7 @@ module MongoModel
23
23
  delegate :foreign_key, :inverse_of, :to => :definition
24
24
 
25
25
  def find_target
26
- klass.find(:all, :conditions => { foreign_key => instance.id }) + new_documents
26
+ send_to_klass_with_scope(:all) + new_documents
27
27
  end
28
28
 
29
29
  def build(*args, &block)
@@ -44,6 +44,18 @@ module MongoModel
44
44
  end
45
45
  end
46
46
 
47
+ def create!(*args, &block)
48
+ klass.create!(*args) do |doc|
49
+ if doc.respond_to?("#{inverse_of}=")
50
+ doc.send("#{inverse_of}=", instance)
51
+ else
52
+ doc[foreign_key] = instance.id
53
+ end
54
+
55
+ block.call(doc) if block
56
+ end
57
+ end
58
+
47
59
  def replace(array)
48
60
  ensure_class(array)
49
61
  array.each { |doc| assign(doc) }
@@ -60,13 +72,25 @@ module MongoModel
60
72
  doc.save(false) unless doc.new_record?
61
73
  end
62
74
 
75
+ def unset(doc)
76
+ if doc.respond_to?("#{inverse_of}=")
77
+ doc.send("#{inverse_of}=", nil) if doc.send(inverse_of) == instance
78
+ else
79
+ doc[foreign_key] = nil if doc[foreign_key] == instance.id
80
+ end
81
+
82
+ doc.save(false) unless doc.new_record?
83
+ end
84
+
63
85
  def send_to_klass_with_scope(*args, &block)
64
- fk = foreign_key
65
- id = instance.id
86
+ scope_options = definition.scope_options
87
+ fk_conditions = { foreign_key => instance.id }
66
88
 
67
89
  klass.instance_eval do
68
- with_scope(:find => { :conditions => { fk => id } }) do
69
- send(*args, &block)
90
+ with_scope(:find => { :conditions => fk_conditions }) do
91
+ with_scope(:find => scope_options) do
92
+ send(*args, &block)
93
+ end
70
94
  end
71
95
  end
72
96
  end
@@ -99,27 +123,31 @@ module MongoModel
99
123
  doc
100
124
  end
101
125
 
102
- def []=(index, doc)
103
- ensure_class(doc)
104
- association.assign(doc)
105
- super if loaded?
106
- self
126
+ def create!(*args, &block)
127
+ doc = association.create!(*args, &block)
128
+ self << doc
129
+ doc
107
130
  end
108
131
 
109
- def <<(doc)
132
+ def []=(index, doc)
110
133
  ensure_class(doc)
134
+ association.unset(target[index]) if target[index]
111
135
  association.assign(doc)
112
136
  super if loaded?
113
137
  self
114
138
  end
115
139
 
116
- def concat(documents)
140
+ def <<(*documents)
141
+ documents.flatten!
117
142
  ensure_class(documents)
118
143
  documents.each { |doc| association.assign(doc) }
119
144
  super if loaded?
120
145
  self
121
146
  end
122
147
 
148
+ alias_method :push, :<<
149
+ alias_method :concat, :<<
150
+
123
151
  def insert(index, doc)
124
152
  ensure_class(doc)
125
153
  association.assign(doc)
@@ -127,17 +155,22 @@ module MongoModel
127
155
  self
128
156
  end
129
157
 
130
- def push(*documents)
158
+ def unshift(*documents)
131
159
  ensure_class(documents)
132
160
  documents.each { |doc| association.assign(doc) }
133
161
  super if loaded?
134
162
  self
135
163
  end
136
164
 
137
- def unshift(*documents)
138
- ensure_class(documents)
139
- documents.each { |doc| association.assign(doc) }
140
- super if loaded?
165
+ def delete(doc)
166
+ association.unset(doc)
167
+ super
168
+ self
169
+ end
170
+
171
+ def delete_at(index)
172
+ association.unset(target[index])
173
+ super
141
174
  self
142
175
  end
143
176
 
@@ -71,7 +71,7 @@ module MongoModel
71
71
  def class_for_type(type)
72
72
  klass = type.constantize
73
73
 
74
- if (subclasses + [name]).include?(type)
74
+ if klass.ancestors.include?(self)
75
75
  klass
76
76
  else
77
77
  raise DocumentNotFound, "Document not of the correct type (got #{type})"
@@ -79,7 +79,7 @@ module MongoModel
79
79
  args << keys.map { |k, o| [k, o == :ascending ? 1 : -1] }.sort_by { |k| k.first.to_s }
80
80
  end
81
81
 
82
- args << true if unique?
82
+ args << { :unique => true } if unique?
83
83
 
84
84
  args
85
85
  end
@@ -51,7 +51,7 @@ module MongoModel
51
51
  end
52
52
 
53
53
  def generate_id
54
- ::Mongo::ObjectID.new.to_s
54
+ ::BSON::ObjectID.new.to_s
55
55
  end
56
56
 
57
57
  module ClassMethods
@@ -1,6 +1,6 @@
1
1
  require 'active_support/core_ext/module/aliasing'
2
2
  require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/object/metaclass'
3
+ require 'active_support/core_ext/kernel/singleton_class'
4
4
 
5
5
  module MongoModel
6
6
  module DocumentExtensions
@@ -23,7 +23,7 @@ module MongoModel
23
23
  def named_scope(name, options={})
24
24
  named_scopes[name] = options
25
25
 
26
- metaclass.instance_eval do
26
+ singleton_class.instance_eval do
27
27
  define_method(name) do |*args|
28
28
  scope(name).apply(*args)
29
29
  end
@@ -1,9 +1,5 @@
1
1
  module MongoModel
2
2
  class EmbeddedDocument
3
- def to_param
4
- id
5
- end
6
-
7
3
  def ==(other)
8
4
  other.is_a?(self.class) && other.attributes == attributes
9
5
  end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/object/blank'
2
-
3
1
  class Boolean < TrueClass; end
4
2
 
5
3
  class Symbol
@@ -10,63 +8,3 @@ class Symbol
10
8
  define_method(:asc) { MongoModel::MongoOrder::Clause.new(self, :ascending) }
11
9
  define_method(:desc) { MongoModel::MongoOrder::Clause.new(self, :descending) }
12
10
  end
13
-
14
- class Class
15
- # Rubinius
16
- if defined?(Class.__subclasses__)
17
- def descendents
18
- subclasses = []
19
- __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendents }
20
- subclasses
21
- end
22
- else
23
- # MRI
24
- begin
25
- ObjectSpace.each_object(Class.new) {}
26
-
27
- def descendents
28
- subclasses = []
29
- ObjectSpace.each_object(class << self; self; end) do |k|
30
- subclasses << k unless k == self
31
- end
32
- subclasses
33
- end
34
- # JRuby
35
- rescue StandardError
36
- def descendents
37
- subclasses = []
38
- ObjectSpace.each_object(Class) do |k|
39
- subclasses << k if k < self
40
- end
41
- subclasses.uniq!
42
- subclasses
43
- end
44
- end
45
- end
46
-
47
- def reachable?
48
- eval("defined?(::#{self}) && ::#{self}.equal?(self)")
49
- end
50
-
51
- def subclasses
52
- Object.subclasses_of(self).map { |o| o.to_s }
53
- end
54
- end
55
-
56
- class Object
57
- def remove_subclasses_of(*superclasses) #:nodoc:
58
- Class.remove_class(*subclasses_of(*superclasses))
59
- end
60
-
61
- # Exclude this class unless it's a subclass of our supers and is defined.
62
- # We check defined? in case we find a removed class that has yet to be
63
- # garbage collected. This also fails for anonymous classes -- please
64
- # submit a patch if you have a workaround.
65
- def subclasses_of(*superclasses) #:nodoc:
66
- subclasses = []
67
- superclasses.each do |klass|
68
- subclasses.concat klass.descendents.select {|k| k.name.blank? || k.reachable?}
69
- end
70
- subclasses
71
- end
72
- end
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/class/subclasses'
2
+
1
3
  module MongoModel
2
4
  class MongoOptions
3
5
  ValidKeys = [ :conditions, :select, :offset, :limit, :order ]
@@ -1,3 +1,3 @@
1
1
  module MongoModel
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.6"
3
3
  end
@@ -0,0 +1,213 @@
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{mongomodel}
8
+ s.version = "0.1.6"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Sam Pohlenz"]
12
+ s.date = %q{2010-04-16}
13
+ s.default_executable = %q{console}
14
+ s.description = %q{MongoModel is a MongoDB ORM for Ruby/Rails similar to ActiveRecord and DataMapper.}
15
+ s.email = %q{sam@sampohlenz.com}
16
+ s.executables = ["console"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "Gemfile",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "bin/console",
28
+ "lib/mongomodel.rb",
29
+ "lib/mongomodel/attributes/mongo.rb",
30
+ "lib/mongomodel/attributes/store.rb",
31
+ "lib/mongomodel/attributes/typecasting.rb",
32
+ "lib/mongomodel/concerns/abstract_class.rb",
33
+ "lib/mongomodel/concerns/activemodel.rb",
34
+ "lib/mongomodel/concerns/associations.rb",
35
+ "lib/mongomodel/concerns/associations/base/association.rb",
36
+ "lib/mongomodel/concerns/associations/base/definition.rb",
37
+ "lib/mongomodel/concerns/associations/base/proxy.rb",
38
+ "lib/mongomodel/concerns/associations/belongs_to.rb",
39
+ "lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb",
40
+ "lib/mongomodel/concerns/associations/has_many_by_ids.rb",
41
+ "lib/mongomodel/concerns/attribute_methods.rb",
42
+ "lib/mongomodel/concerns/attribute_methods/before_type_cast.rb",
43
+ "lib/mongomodel/concerns/attribute_methods/dirty.rb",
44
+ "lib/mongomodel/concerns/attribute_methods/protected.rb",
45
+ "lib/mongomodel/concerns/attribute_methods/query.rb",
46
+ "lib/mongomodel/concerns/attribute_methods/read.rb",
47
+ "lib/mongomodel/concerns/attribute_methods/write.rb",
48
+ "lib/mongomodel/concerns/attributes.rb",
49
+ "lib/mongomodel/concerns/callbacks.rb",
50
+ "lib/mongomodel/concerns/logging.rb",
51
+ "lib/mongomodel/concerns/pretty_inspect.rb",
52
+ "lib/mongomodel/concerns/properties.rb",
53
+ "lib/mongomodel/concerns/record_status.rb",
54
+ "lib/mongomodel/concerns/serialization.rb",
55
+ "lib/mongomodel/concerns/timestamps.rb",
56
+ "lib/mongomodel/concerns/translation.rb",
57
+ "lib/mongomodel/concerns/validations.rb",
58
+ "lib/mongomodel/concerns/validations/associated.rb",
59
+ "lib/mongomodel/document.rb",
60
+ "lib/mongomodel/document/callbacks.rb",
61
+ "lib/mongomodel/document/dynamic_finders.rb",
62
+ "lib/mongomodel/document/finders.rb",
63
+ "lib/mongomodel/document/indexes.rb",
64
+ "lib/mongomodel/document/optimistic_locking.rb",
65
+ "lib/mongomodel/document/persistence.rb",
66
+ "lib/mongomodel/document/scopes.rb",
67
+ "lib/mongomodel/document/validations.rb",
68
+ "lib/mongomodel/document/validations/uniqueness.rb",
69
+ "lib/mongomodel/embedded_document.rb",
70
+ "lib/mongomodel/locale/en.yml",
71
+ "lib/mongomodel/support/collection.rb",
72
+ "lib/mongomodel/support/configuration.rb",
73
+ "lib/mongomodel/support/core_extensions.rb",
74
+ "lib/mongomodel/support/exceptions.rb",
75
+ "lib/mongomodel/support/mongo_options.rb",
76
+ "lib/mongomodel/support/types.rb",
77
+ "lib/mongomodel/support/types/array.rb",
78
+ "lib/mongomodel/support/types/boolean.rb",
79
+ "lib/mongomodel/support/types/custom.rb",
80
+ "lib/mongomodel/support/types/date.rb",
81
+ "lib/mongomodel/support/types/float.rb",
82
+ "lib/mongomodel/support/types/hash.rb",
83
+ "lib/mongomodel/support/types/integer.rb",
84
+ "lib/mongomodel/support/types/object.rb",
85
+ "lib/mongomodel/support/types/string.rb",
86
+ "lib/mongomodel/support/types/symbol.rb",
87
+ "lib/mongomodel/support/types/time.rb",
88
+ "lib/mongomodel/version.rb",
89
+ "mongomodel.gemspec",
90
+ "spec/mongomodel/attributes/store_spec.rb",
91
+ "spec/mongomodel/concerns/activemodel_spec.rb",
92
+ "spec/mongomodel/concerns/associations/belongs_to_spec.rb",
93
+ "spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb",
94
+ "spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb",
95
+ "spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb",
96
+ "spec/mongomodel/concerns/attribute_methods/dirty_spec.rb",
97
+ "spec/mongomodel/concerns/attribute_methods/protected_spec.rb",
98
+ "spec/mongomodel/concerns/attribute_methods/query_spec.rb",
99
+ "spec/mongomodel/concerns/attribute_methods/read_spec.rb",
100
+ "spec/mongomodel/concerns/attribute_methods/write_spec.rb",
101
+ "spec/mongomodel/concerns/attributes_spec.rb",
102
+ "spec/mongomodel/concerns/callbacks_spec.rb",
103
+ "spec/mongomodel/concerns/logging_spec.rb",
104
+ "spec/mongomodel/concerns/pretty_inspect_spec.rb",
105
+ "spec/mongomodel/concerns/properties_spec.rb",
106
+ "spec/mongomodel/concerns/serialization/json_serialization_spec.rb",
107
+ "spec/mongomodel/concerns/timestamps_spec.rb",
108
+ "spec/mongomodel/concerns/translation_spec.rb",
109
+ "spec/mongomodel/concerns/validations_spec.rb",
110
+ "spec/mongomodel/document/callbacks_spec.rb",
111
+ "spec/mongomodel/document/dynamic_finders_spec.rb",
112
+ "spec/mongomodel/document/finders_spec.rb",
113
+ "spec/mongomodel/document/indexes_spec.rb",
114
+ "spec/mongomodel/document/optimistic_locking_spec.rb",
115
+ "spec/mongomodel/document/persistence_spec.rb",
116
+ "spec/mongomodel/document/scopes_spec.rb",
117
+ "spec/mongomodel/document/validations/uniqueness_spec.rb",
118
+ "spec/mongomodel/document/validations_spec.rb",
119
+ "spec/mongomodel/document_spec.rb",
120
+ "spec/mongomodel/embedded_document_spec.rb",
121
+ "spec/mongomodel/mongomodel_spec.rb",
122
+ "spec/mongomodel/support/collection_spec.rb",
123
+ "spec/mongomodel/support/mongo_options_spec.rb",
124
+ "spec/mongomodel/support/property_spec.rb",
125
+ "spec/spec.opts",
126
+ "spec/spec_helper.rb",
127
+ "spec/specdoc.opts",
128
+ "spec/support/callbacks.rb",
129
+ "spec/support/helpers/define_class.rb",
130
+ "spec/support/helpers/specs_for.rb",
131
+ "spec/support/matchers/be_a_subclass_of.rb",
132
+ "spec/support/matchers/be_truthy.rb",
133
+ "spec/support/matchers/respond_to_boolean.rb",
134
+ "spec/support/matchers/run_callbacks.rb",
135
+ "spec/support/models.rb",
136
+ "spec/support/time.rb"
137
+ ]
138
+ s.homepage = %q{http://github.com/spohlenz/mongomodel}
139
+ s.rdoc_options = ["--charset=UTF-8"]
140
+ s.require_paths = ["lib"]
141
+ s.rubygems_version = %q{1.3.6}
142
+ s.summary = %q{MongoDB ORM for Ruby/Rails}
143
+ s.test_files = [
144
+ "spec/mongomodel/attributes/store_spec.rb",
145
+ "spec/mongomodel/concerns/activemodel_spec.rb",
146
+ "spec/mongomodel/concerns/associations/belongs_to_spec.rb",
147
+ "spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb",
148
+ "spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb",
149
+ "spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb",
150
+ "spec/mongomodel/concerns/attribute_methods/dirty_spec.rb",
151
+ "spec/mongomodel/concerns/attribute_methods/protected_spec.rb",
152
+ "spec/mongomodel/concerns/attribute_methods/query_spec.rb",
153
+ "spec/mongomodel/concerns/attribute_methods/read_spec.rb",
154
+ "spec/mongomodel/concerns/attribute_methods/write_spec.rb",
155
+ "spec/mongomodel/concerns/attributes_spec.rb",
156
+ "spec/mongomodel/concerns/callbacks_spec.rb",
157
+ "spec/mongomodel/concerns/logging_spec.rb",
158
+ "spec/mongomodel/concerns/pretty_inspect_spec.rb",
159
+ "spec/mongomodel/concerns/properties_spec.rb",
160
+ "spec/mongomodel/concerns/serialization/json_serialization_spec.rb",
161
+ "spec/mongomodel/concerns/timestamps_spec.rb",
162
+ "spec/mongomodel/concerns/translation_spec.rb",
163
+ "spec/mongomodel/concerns/validations_spec.rb",
164
+ "spec/mongomodel/document/callbacks_spec.rb",
165
+ "spec/mongomodel/document/dynamic_finders_spec.rb",
166
+ "spec/mongomodel/document/finders_spec.rb",
167
+ "spec/mongomodel/document/indexes_spec.rb",
168
+ "spec/mongomodel/document/optimistic_locking_spec.rb",
169
+ "spec/mongomodel/document/persistence_spec.rb",
170
+ "spec/mongomodel/document/scopes_spec.rb",
171
+ "spec/mongomodel/document/validations/uniqueness_spec.rb",
172
+ "spec/mongomodel/document/validations_spec.rb",
173
+ "spec/mongomodel/document_spec.rb",
174
+ "spec/mongomodel/embedded_document_spec.rb",
175
+ "spec/mongomodel/mongomodel_spec.rb",
176
+ "spec/mongomodel/support/collection_spec.rb",
177
+ "spec/mongomodel/support/mongo_options_spec.rb",
178
+ "spec/mongomodel/support/property_spec.rb",
179
+ "spec/spec_helper.rb",
180
+ "spec/support/callbacks.rb",
181
+ "spec/support/helpers/define_class.rb",
182
+ "spec/support/helpers/specs_for.rb",
183
+ "spec/support/matchers/be_a_subclass_of.rb",
184
+ "spec/support/matchers/be_truthy.rb",
185
+ "spec/support/matchers/respond_to_boolean.rb",
186
+ "spec/support/matchers/run_callbacks.rb",
187
+ "spec/support/models.rb",
188
+ "spec/support/time.rb"
189
+ ]
190
+
191
+ if s.respond_to? :specification_version then
192
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
193
+ s.specification_version = 3
194
+
195
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
196
+ s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0.beta3"])
197
+ s.add_runtime_dependency(%q<activemodel>, [">= 3.0.0.beta3"])
198
+ s.add_runtime_dependency(%q<mongo>, [">= 0.20.1"])
199
+ s.add_runtime_dependency(%q<bson>, [">= 0.20.1"])
200
+ else
201
+ s.add_dependency(%q<activesupport>, [">= 3.0.0.beta3"])
202
+ s.add_dependency(%q<activemodel>, [">= 3.0.0.beta3"])
203
+ s.add_dependency(%q<mongo>, [">= 0.20.1"])
204
+ s.add_dependency(%q<bson>, [">= 0.20.1"])
205
+ end
206
+ else
207
+ s.add_dependency(%q<activesupport>, [">= 3.0.0.beta3"])
208
+ s.add_dependency(%q<activemodel>, [">= 3.0.0.beta3"])
209
+ s.add_dependency(%q<mongo>, [">= 0.20.1"])
210
+ s.add_dependency(%q<bson>, [">= 0.20.1"])
211
+ end
212
+ end
213
+
@@ -1,33 +1,97 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  # Specs ported from ActiveModel::Lint::Tests
4
+ #
5
+ # These tests do not attempt to determine the semantic correctness of the
6
+ # returned values. For instance, you could implement valid? to always
7
+ # return true, and the tests would pass. It is up to you to ensure that
8
+ # the values are semantically meaningful.
9
+ #
10
+ # Objects you pass in are expected to return a compliant object from a
11
+ # call to to_model. It is perfectly fine for to_model to return self.
4
12
  module MongoModel
5
13
  specs_for(Document, EmbeddedDocument) do
6
14
  define_class(:TestModel, described_class)
7
15
 
8
16
  subject { TestModel.new.to_model }
9
17
 
10
- # valid?
11
- # ------
18
+ # == Responds to <tt>to_key</tt>
12
19
  #
13
- # Returns a boolean that specifies whether the object is in a valid or invalid
14
- # state.
15
- it { should respond_to_boolean(:valid?) }
16
-
17
- # new_record?
18
- # -----------
20
+ # Returns an Enumerable of all (primary) key attributes
21
+ # or nil if model.persisted? is false
22
+ it { should respond_to(:to_key) }
23
+
24
+ specify "to_key should return nil if subject.persisted? is false" do
25
+ subject.stub!(:persisted?).and_return(false)
26
+ subject.to_key.should be_nil
27
+ end
28
+
29
+ # == Responds to <tt>to_param</tt>
30
+ #
31
+ # Returns a string representing the object's key suitable for use in URLs
32
+ # or nil if model.persisted? is false.
33
+ #
34
+ # Implementers can decide to either raise an exception or provide a default
35
+ # in case the record uses a composite primary key. There are no tests for this
36
+ # behavior in lint because it doesn't make sense to force any of the possible
37
+ # implementation strategies on the implementer. However, if the resource is
38
+ # not persisted?, then to_param should always return nil.
39
+ it { should respond_to(:to_param) }
40
+
41
+ specify "to_param should return nil if subject.persisted? is false" do
42
+ subject.stub!(:persisted?).and_return(false)
43
+ subject.to_param.should be_nil
44
+ end
45
+
46
+ # == Responds to <tt>persisted?</tt>
19
47
  #
20
48
  # Returns a boolean that specifies whether the object has been persisted yet.
21
49
  # This is used when calculating the URL for an object. If the object is
22
50
  # not persisted, a form for that object, for instance, will be POSTed to the
23
51
  # collection. If it is persisted, a form for the object will put PUTed to the
24
52
  # URL for the object.
25
- it { should respond_to_boolean(:new_record?) }
26
- it { should respond_to_boolean(:destroyed?) }
53
+ it { should respond_to_boolean(:persisted?) }
27
54
 
28
- # errors
29
- # ------
55
+ # == Naming
30
56
  #
57
+ # Model.model_name must returns a string with some convenience methods as
58
+ # :human and :partial_path. Check ActiveModel::Naming for more information.
59
+ #
60
+ specify "the model class should respond to model_name" do
61
+ subject.class.should respond_to(:model_name)
62
+ end
63
+
64
+ it "should return strings for model_name" do
65
+ model_name = subject.class.model_name
66
+ model_name.should be_a_kind_of(String)
67
+ model_name.human.should be_a_kind_of(String)
68
+ model_name.partial_path.should be_a_kind_of(String)
69
+ model_name.singular.should be_a_kind_of(String)
70
+ model_name.plural.should be_a_kind_of(String)
71
+ end
72
+
73
+ # ## Old
74
+ #
75
+ # # valid?
76
+ # # ------
77
+ # #
78
+ # # Returns a boolean that specifies whether the object is in a valid or invalid
79
+ # # state.
80
+ # it { should respond_to_boolean(:valid?) }
81
+ #
82
+ # # new_record?
83
+ # # -----------
84
+ # #
85
+ # # Returns a boolean that specifies whether the object has been persisted yet.
86
+ # # This is used when calculating the URL for an object. If the object is
87
+ # # not persisted, a form for that object, for instance, will be POSTed to the
88
+ # # collection. If it is persisted, a form for the object will put PUTed to the
89
+ # # URL for the object.
90
+ # it { should respond_to_boolean(:new_record?) }
91
+ # it { should respond_to_boolean(:destroyed?) }
92
+
93
+ # == Errors Testing
94
+ #
31
95
  # Returns an object that has :[] and :full_messages defined on it. See below
32
96
  # for more details.
33
97
  describe "errors" do
@@ -51,11 +115,5 @@ module MongoModel
51
115
  end
52
116
  end
53
117
  end
54
-
55
- describe "#model_name" do
56
- it "should return an ActiveModel::Name object" do
57
- TestModel.model_name.should == ActiveModel::Name.new(mock('TestModel class', :name => 'TestModel'))
58
- end
59
- end
60
118
  end
61
119
  end
@@ -20,6 +20,10 @@ module MongoModel
20
20
  subject.user.should == user
21
21
  end
22
22
 
23
+ it "should not be truthy" do
24
+ subject.user.should_not be_truthy
25
+ end
26
+
23
27
  describe "setting a subclass type" do
24
28
  it "should set successfully" do
25
29
  subject.user = special_user
@@ -47,12 +51,16 @@ module MongoModel
47
51
  reloaded.user.should == user
48
52
  end
49
53
 
54
+ it "should be truthy" do
55
+ subject.user.should be_truthy
56
+ end
57
+
50
58
  it "should allow the user to be reloaded" do
51
- reloaded.user.inspect
52
- reloaded.user.loaded?.should be_true
59
+ user = reloaded.user.target
53
60
 
54
- reloaded.user(true)
55
- reloaded.user.loaded?.should be_false
61
+ user.should equal(reloaded.user.target)
62
+ user.should equal(reloaded.user.target)
63
+ user.should_not equal(reloaded.user(true).target)
56
64
  end
57
65
 
58
66
  describe "setting a subclass type" do
@@ -18,7 +18,7 @@ module MongoModel
18
18
  end
19
19
  define_class(:IllustratedChapter, :Chapter)
20
20
  define_class(:Book, Document) do
21
- has_many :chapters, :by => :foreign_key
21
+ has_many :chapters, :by => :foreign_key, :limit => 5
22
22
  end
23
23
  define_class(:NonChapter, Document)
24
24
 
@@ -56,6 +56,13 @@ module MongoModel
56
56
  chapter3.book.should == subject
57
57
  end
58
58
 
59
+ it "should replace chapters with []=" do
60
+ subject.chapters[1] = chapter3
61
+ subject.chapters.should include(chapter1, chapter3)
62
+ subject.chapters.should_not include(chapter2)
63
+ #chapter2.book.should be_nil
64
+ end
65
+
59
66
  it "should add chapters with concat" do
60
67
  subject.chapters.concat([chapter3])
61
68
  subject.chapters.should include(chapter1, chapter2, chapter3)
@@ -89,21 +96,21 @@ module MongoModel
89
96
  # it "should clear chapters" do
90
97
  # subject.chapters.clear
91
98
  # subject.chapters.should be_empty
92
- # subject.chapter_ids.should be_empty
93
- # end
94
- #
95
- # it "should remove chapters with delete" do
96
- # subject.chapters.delete(chapter1)
97
- # subject.chapters.should == [chapter2]
98
- # subject.chapter_ids.should == [chapter2.id]
99
+ # [chapter1, chapter2].each { |c| c.book.should be_nil }
99
100
  # end
100
- #
101
- # it "should remove chapters with delete_at" do
102
- # subject.chapters.delete_at(0)
103
- # subject.chapters.should == [chapter2]
104
- # subject.chapter_ids.should == [chapter2.id]
105
- # end
106
- #
101
+
102
+ it "should remove chapters with delete" do
103
+ subject.chapters.delete(chapter1)
104
+ subject.chapters.should == [chapter2]
105
+ chapter1.book.should be_nil
106
+ end
107
+
108
+ it "should remove chapters with delete_at" do
109
+ subject.chapters.delete_at(0)
110
+ subject.chapters.should == [chapter2]
111
+ #chapter1.book.should be_nil
112
+ end
113
+
107
114
  # it "should remove chapters with delete_if" do
108
115
  # subject.chapters.delete_if { |c| c.id == chapter1.id }
109
116
  # subject.chapters.should == [chapter2]
@@ -138,9 +145,16 @@ module MongoModel
138
145
  result = subject.chapters.find(:all, :order => :id.desc)
139
146
  result.should == [chapter2, chapter1]
140
147
  end
148
+
149
+ it "should find chapters with association options" do
150
+ # Create bogus chapters
151
+ 10.times { subject.chapters.create! }
152
+
153
+ subject.chapters.all.size.should == 5 # limit clause
154
+ end
141
155
  end
142
156
 
143
- context "with chapters set" do
157
+ context "new instance with chapters set" do
144
158
  subject { Book.new(:chapters => [chapter1, chapter2]) }
145
159
  it_should_behave_like "accessing and manipulating a has_many :by => :foreign_key association"
146
160
  end
@@ -45,7 +45,7 @@ module MongoModel
45
45
 
46
46
  it "should create indexes on the collection" do
47
47
  Article.collection.should_receive(:create_index).with(:_type)
48
- Article.collection.should_receive(:create_index).with(:title, true)
48
+ Article.collection.should_receive(:create_index).with(:title, :unique => true)
49
49
  Article.collection.should_receive(:create_index).with([[:age, Mongo::DESCENDING]])
50
50
  Article.ensure_indexes!
51
51
  end
@@ -93,7 +93,7 @@ module MongoModel
93
93
  end
94
94
 
95
95
  it "should convert index with unique option to arguments for Mongo::Collection#create_index" do
96
- Index.new(:title, :unique => true).to_args.should == [:title, true]
96
+ Index.new(:title, :unique => true).to_args.should == [:title, { :unique => true }]
97
97
  end
98
98
 
99
99
  it "should convert index with descending key to arguments for Mongo::Collection#create_index" do
@@ -58,6 +58,12 @@ module MongoModel
58
58
  subject.should be_valid
59
59
  end
60
60
 
61
+ it "should generate correct error message" do
62
+ Article.create!(:title => 'Test')
63
+ subject.valid?
64
+ subject.errors[:title].should include('has already been taken')
65
+ end
66
+
61
67
  describe "beating the race condition" do
62
68
  before(:each) { Article.create!(:title => 'Test') }
63
69
  it_should_behave_like "beating the race condition"
@@ -1,4 +1,13 @@
1
- require 'rubygems'
1
+ begin
2
+ # Try to require the preresolved locked set of gems.
3
+ require File.expand_path('../../.bundle/environment', __FILE__)
4
+ rescue LoadError
5
+ # Fall back on doing an unlocked resolve at runtime.
6
+ require "rubygems"
7
+ require "bundler"
8
+ Bundler.setup
9
+ end
10
+
2
11
  require 'spec'
3
12
 
4
13
  # Require MongoModel library
@@ -0,0 +1,5 @@
1
+ Spec::Matchers.define(:be_truthy) do
2
+ match do |object|
3
+ !!object
4
+ end
5
+ end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongomodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 6
9
+ version: 0.1.6
5
10
  platform: ruby
6
11
  authors:
7
12
  - Sam Pohlenz
@@ -9,39 +14,67 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-02-19 00:00:00 +10:30
17
+ date: 2010-04-16 00:00:00 +09:30
13
18
  default_executable: console
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: activesupport
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
23
- version: 3.0.pre
24
- version:
27
+ segments:
28
+ - 3
29
+ - 0
30
+ - 0
31
+ - beta3
32
+ version: 3.0.0.beta3
33
+ type: :runtime
34
+ version_requirements: *id001
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: activemodel
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
30
39
  requirements:
31
40
  - - ">="
32
41
  - !ruby/object:Gem::Version
33
- version: 3.0.pre
34
- version:
42
+ segments:
43
+ - 3
44
+ - 0
45
+ - 0
46
+ - beta3
47
+ version: 3.0.0.beta3
48
+ type: :runtime
49
+ version_requirements: *id002
35
50
  - !ruby/object:Gem::Dependency
36
51
  name: mongo
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ - 20
60
+ - 1
61
+ version: 0.20.1
37
62
  type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
63
+ version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: bson
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
40
68
  requirements:
41
69
  - - ">="
42
70
  - !ruby/object:Gem::Version
43
- version: 0.18.3
44
- version:
71
+ segments:
72
+ - 0
73
+ - 20
74
+ - 1
75
+ version: 0.20.1
76
+ type: :runtime
77
+ version_requirements: *id004
45
78
  description: MongoModel is a MongoDB ORM for Ruby/Rails similar to ActiveRecord and DataMapper.
46
79
  email: sam@sampohlenz.com
47
80
  executables:
@@ -52,6 +85,8 @@ extra_rdoc_files:
52
85
  - LICENSE
53
86
  - README.md
54
87
  files:
88
+ - .gitignore
89
+ - Gemfile
55
90
  - LICENSE
56
91
  - README.md
57
92
  - Rakefile
@@ -117,6 +152,7 @@ files:
117
152
  - lib/mongomodel/support/types/symbol.rb
118
153
  - lib/mongomodel/support/types/time.rb
119
154
  - lib/mongomodel/version.rb
155
+ - mongomodel.gemspec
120
156
  - spec/mongomodel/attributes/store_spec.rb
121
157
  - spec/mongomodel/concerns/activemodel_spec.rb
122
158
  - spec/mongomodel/concerns/associations/belongs_to_spec.rb
@@ -159,6 +195,7 @@ files:
159
195
  - spec/support/helpers/define_class.rb
160
196
  - spec/support/helpers/specs_for.rb
161
197
  - spec/support/matchers/be_a_subclass_of.rb
198
+ - spec/support/matchers/be_truthy.rb
162
199
  - spec/support/matchers/respond_to_boolean.rb
163
200
  - spec/support/matchers/run_callbacks.rb
164
201
  - spec/support/models.rb
@@ -176,18 +213,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
213
  requirements:
177
214
  - - ">="
178
215
  - !ruby/object:Gem::Version
216
+ segments:
217
+ - 0
179
218
  version: "0"
180
- version:
181
219
  required_rubygems_version: !ruby/object:Gem::Requirement
182
220
  requirements:
183
221
  - - ">="
184
222
  - !ruby/object:Gem::Version
223
+ segments:
224
+ - 0
185
225
  version: "0"
186
- version:
187
226
  requirements: []
188
227
 
189
228
  rubyforge_project:
190
- rubygems_version: 1.3.5
229
+ rubygems_version: 1.3.6
191
230
  signing_key:
192
231
  specification_version: 3
193
232
  summary: MongoDB ORM for Ruby/Rails
@@ -232,6 +271,7 @@ test_files:
232
271
  - spec/support/helpers/define_class.rb
233
272
  - spec/support/helpers/specs_for.rb
234
273
  - spec/support/matchers/be_a_subclass_of.rb
274
+ - spec/support/matchers/be_truthy.rb
235
275
  - spec/support/matchers/respond_to_boolean.rb
236
276
  - spec/support/matchers/run_callbacks.rb
237
277
  - spec/support/models.rb