mongomodel 0.5.5 → 0.5.6
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.
- checksums.yaml +5 -5
- data/.travis.yml +23 -11
- data/gemfiles/rails-3.2.gemfile +2 -2
- data/gemfiles/rails-4-observers.gemfile +1 -1
- data/gemfiles/rails-4.1.gemfile +2 -2
- data/gemfiles/{mongoid.gemfile → rails-4.2.gemfile} +2 -3
- data/gemfiles/{mongo_mapper.gemfile → rails-5.0.gemfile} +2 -3
- data/gemfiles/rails-5.1.gemfile +10 -0
- data/gemfiles/rails-5.2.gemfile +10 -0
- data/lib/mongomodel.rb +15 -15
- data/lib/mongomodel/attributes/mongo.rb +7 -7
- data/lib/mongomodel/attributes/store.rb +4 -4
- data/lib/mongomodel/attributes/typecasting.rb +7 -7
- data/lib/mongomodel/compatibility/mongo_mapper.rb +3 -3
- data/lib/mongomodel/compatibility/mongoid.rb +3 -3
- data/lib/mongomodel/concerns/abstract_class.rb +3 -3
- data/lib/mongomodel/concerns/activemodel.rb +4 -4
- data/lib/mongomodel/concerns/associations.rb +8 -8
- data/lib/mongomodel/concerns/associations/base/association.rb +5 -5
- data/lib/mongomodel/concerns/associations/base/definition.rb +4 -4
- data/lib/mongomodel/concerns/associations/base/proxy.rb +1 -1
- data/lib/mongomodel/concerns/associations/belongs_to.rb +19 -19
- data/lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb +36 -36
- data/lib/mongomodel/concerns/associations/has_many_by_ids.rb +34 -34
- data/lib/mongomodel/concerns/attribute_methods.rb +10 -10
- data/lib/mongomodel/concerns/attribute_methods/before_type_cast.rb +4 -4
- data/lib/mongomodel/concerns/attribute_methods/dirty.rb +95 -13
- data/lib/mongomodel/concerns/attribute_methods/forbidden.rb +1 -1
- data/lib/mongomodel/concerns/attribute_methods/multi_parameter_assignment.rb +6 -6
- data/lib/mongomodel/concerns/attribute_methods/nested.rb +18 -18
- data/lib/mongomodel/concerns/attribute_methods/protected.rb +3 -3
- data/lib/mongomodel/concerns/attribute_methods/query.rb +3 -3
- data/lib/mongomodel/concerns/attribute_methods/read.rb +4 -4
- data/lib/mongomodel/concerns/attribute_methods/write.rb +4 -4
- data/lib/mongomodel/concerns/attributes.rb +18 -18
- data/lib/mongomodel/concerns/callbacks.rb +7 -7
- data/lib/mongomodel/concerns/document_parent.rb +2 -2
- data/lib/mongomodel/concerns/logging.rb +2 -2
- data/lib/mongomodel/concerns/map_reduce.rb +11 -11
- data/lib/mongomodel/concerns/pretty_inspect.rb +3 -3
- data/lib/mongomodel/concerns/properties.rb +18 -18
- data/lib/mongomodel/concerns/record_status.rb +9 -13
- data/lib/mongomodel/concerns/serialization.rb +4 -4
- data/lib/mongomodel/concerns/timestamps.rb +4 -4
- data/lib/mongomodel/concerns/translation.rb +2 -2
- data/lib/mongomodel/concerns/validations.rb +5 -5
- data/lib/mongomodel/concerns/validations/associated.rb +1 -1
- data/lib/mongomodel/document.rb +6 -6
- data/lib/mongomodel/document/callbacks.rb +15 -21
- data/lib/mongomodel/document/collection_modifiers.rb +5 -5
- data/lib/mongomodel/document/dynamic_finders.rb +1 -1
- data/lib/mongomodel/document/indexes.rb +19 -19
- data/lib/mongomodel/document/optimistic_locking.rb +7 -7
- data/lib/mongomodel/document/persistence.rb +23 -23
- data/lib/mongomodel/document/scopes.rb +20 -20
- data/lib/mongomodel/document/validations.rb +6 -6
- data/lib/mongomodel/document/validations/uniqueness.rb +11 -11
- data/lib/mongomodel/embedded_document.rb +11 -11
- data/lib/mongomodel/locale/en.yml +0 -1
- data/lib/mongomodel/log_subscriber.rb +5 -5
- data/lib/mongomodel/railtie.rb +13 -13
- data/lib/mongomodel/support/collection.rb +31 -31
- data/lib/mongomodel/support/configuration.rb +11 -11
- data/lib/mongomodel/support/core_extensions.rb +1 -1
- data/lib/mongomodel/support/dynamic_finder.rb +12 -12
- data/lib/mongomodel/support/exceptions.rb +6 -6
- data/lib/mongomodel/support/instrumented_collection.rb +20 -20
- data/lib/mongomodel/support/map.rb +33 -33
- data/lib/mongomodel/support/mongo_operator.rb +6 -6
- data/lib/mongomodel/support/mongo_options.rb +18 -18
- data/lib/mongomodel/support/mongo_order.rb +16 -16
- data/lib/mongomodel/support/paginator.rb +8 -8
- data/lib/mongomodel/support/reference.rb +10 -10
- data/lib/mongomodel/support/scope.rb +37 -37
- data/lib/mongomodel/support/scope/array_methods.rb +1 -1
- data/lib/mongomodel/support/scope/batches.rb +1 -1
- data/lib/mongomodel/support/scope/dynamic_finders.rb +1 -1
- data/lib/mongomodel/support/scope/finder_methods.rb +7 -7
- data/lib/mongomodel/support/scope/load_methods.rb +1 -1
- data/lib/mongomodel/support/scope/pagination.rb +1 -1
- data/lib/mongomodel/support/scope/query_methods.rb +6 -6
- data/lib/mongomodel/support/scope/spawn_methods.rb +8 -8
- data/lib/mongomodel/support/types.rb +2 -2
- data/lib/mongomodel/support/types/array.rb +1 -1
- data/lib/mongomodel/support/types/boolean.rb +3 -3
- data/lib/mongomodel/support/types/custom.rb +3 -3
- data/lib/mongomodel/support/types/date.rb +2 -2
- data/lib/mongomodel/support/types/date_time.rb +6 -16
- data/lib/mongomodel/support/types/float.rb +1 -1
- data/lib/mongomodel/support/types/hash.rb +1 -1
- data/lib/mongomodel/support/types/integer.rb +13 -10
- data/lib/mongomodel/support/types/object.rb +5 -5
- data/lib/mongomodel/support/types/rational.rb +3 -3
- data/lib/mongomodel/support/types/time.rb +2 -2
- data/lib/mongomodel/version.rb +1 -1
- data/lib/rails/generators/mongo_model/config/templates/mongomodel.yml +3 -4
- data/lib/rails/generators/mongo_model/model/model_generator.rb +3 -3
- data/mongomodel.gemspec +5 -4
- data/spec/mongomodel/attributes/store_spec.rb +21 -21
- data/spec/mongomodel/concerns/activemodel_spec.rb +4 -4
- data/spec/mongomodel/concerns/associations/base/association_spec.rb +12 -12
- data/spec/mongomodel/concerns/associations/belongs_to_spec.rb +34 -21
- data/spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb +53 -53
- data/spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb +30 -30
- data/spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb +7 -7
- data/spec/mongomodel/concerns/attribute_methods/dirty_spec.rb +45 -41
- data/spec/mongomodel/concerns/attribute_methods/multi_parameter_assignment_spec.rb +7 -7
- data/spec/mongomodel/concerns/attribute_methods/nested_spec.rb +31 -31
- data/spec/mongomodel/concerns/attribute_methods/protected_spec.rb +15 -15
- data/spec/mongomodel/concerns/attribute_methods/query_spec.rb +19 -19
- data/spec/mongomodel/concerns/attribute_methods/read_spec.rb +9 -9
- data/spec/mongomodel/concerns/attribute_methods/write_spec.rb +6 -6
- data/spec/mongomodel/concerns/attribute_methods_spec.rb +13 -13
- data/spec/mongomodel/concerns/attributes_spec.rb +34 -34
- data/spec/mongomodel/concerns/callbacks_spec.rb +25 -21
- data/spec/mongomodel/concerns/logging_spec.rb +5 -3
- data/spec/mongomodel/concerns/map_reduce_spec.rb +19 -19
- data/spec/mongomodel/concerns/observing_spec.rb +3 -3
- data/spec/mongomodel/concerns/pretty_inspect_spec.rb +10 -10
- data/spec/mongomodel/concerns/properties_spec.rb +11 -11
- data/spec/mongomodel/concerns/serialization/json_serialization_spec.rb +13 -13
- data/spec/mongomodel/concerns/timestamps_spec.rb +39 -39
- data/spec/mongomodel/concerns/validations_spec.rb +41 -38
- data/spec/mongomodel/document/callbacks_spec.rb +20 -16
- data/spec/mongomodel/document/collection_modifiers_spec.rb +16 -16
- data/spec/mongomodel/document/dynamic_finders_spec.rb +46 -46
- data/spec/mongomodel/document/finders_spec.rb +15 -15
- data/spec/mongomodel/document/indexes_spec.rb +29 -29
- data/spec/mongomodel/document/optimistic_locking_spec.rb +16 -16
- data/spec/mongomodel/document/persistence_spec.rb +39 -39
- data/spec/mongomodel/document/scopes_spec.rb +17 -17
- data/spec/mongomodel/document/validations/uniqueness_spec.rb +46 -46
- data/spec/mongomodel/document/validations_spec.rb +35 -35
- data/spec/mongomodel/document_spec.rb +19 -19
- data/spec/mongomodel/embedded_document_spec.rb +19 -19
- data/spec/mongomodel/mongomodel_spec.rb +7 -6
- data/spec/mongomodel/support/collection_spec.rb +54 -54
- data/spec/mongomodel/support/configuration_spec.rb +1 -1
- data/spec/mongomodel/support/map_spec.rb +66 -66
- data/spec/mongomodel/support/mongo_operator_spec.rb +5 -5
- data/spec/mongomodel/support/mongo_options_spec.rb +42 -42
- data/spec/mongomodel/support/mongo_order_spec.rb +24 -24
- data/spec/mongomodel/support/paginator_spec.rb +15 -15
- data/spec/mongomodel/support/property_spec.rb +29 -23
- data/spec/mongomodel/support/scope_spec.rb +205 -204
- data/spec/spec_helper.rb +13 -2
- data/spec/support/callbacks.rb +3 -8
- data/spec/support/helpers/define_class.rb +7 -7
- data/spec/support/helpers/document_finder_stubs.rb +6 -6
- data/spec/support/helpers/specs_for.rb +1 -1
- data/spec/support/helpers/validations.rb +1 -1
- data/spec/support/matchers/find_with.rb +8 -8
- data/spec/support/matchers/respond_to_boolean.rb +3 -3
- data/spec/support/matchers/run_callbacks.rb +6 -9
- data/spec/support/models.rb +5 -5
- metadata +23 -7
|
@@ -6,16 +6,16 @@ module MongoModel
|
|
|
6
6
|
source_root File.expand_path('../templates', __FILE__)
|
|
7
7
|
|
|
8
8
|
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
class_option :timestamps, :type => :boolean, :aliases => "-T", :default => true, :desc => "Add timestamp fields (created_at, updated_at)"
|
|
11
11
|
class_option :embedded, :type => :boolean, :aliases => "-E", :default => false, :desc => "Inherit from EmbeddedDocument"
|
|
12
12
|
|
|
13
13
|
check_class_collision
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
def create_model_file
|
|
16
16
|
template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
hook_for :test_framework
|
|
20
20
|
end
|
|
21
21
|
end
|
data/mongomodel.gemspec
CHANGED
|
@@ -14,14 +14,15 @@ Gem::Specification.new do |s|
|
|
|
14
14
|
|
|
15
15
|
s.required_rubygems_version = ">= 1.3.6"
|
|
16
16
|
s.rubyforge_project = "mongomodel"
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
s.add_dependency "activesupport", ">= 3.1"
|
|
19
19
|
s.add_dependency "activemodel", ">= 3.1"
|
|
20
20
|
s.add_dependency "mongo", "~> 1.8"
|
|
21
21
|
|
|
22
|
-
s.add_development_dependency "bundler",
|
|
23
|
-
s.add_development_dependency "rspec",
|
|
24
|
-
s.add_development_dependency "
|
|
22
|
+
s.add_development_dependency "bundler", ">= 1.0"
|
|
23
|
+
s.add_development_dependency "rspec", "~> 3.5"
|
|
24
|
+
s.add_development_dependency "rspec-its", "~> 1.2"
|
|
25
|
+
s.add_development_dependency "minitest", ">= 4.2"
|
|
25
26
|
|
|
26
27
|
s.files = `git ls-files`.split("\n")
|
|
27
28
|
s.require_path = 'lib'
|
|
@@ -28,18 +28,18 @@ module MongoModel
|
|
|
28
28
|
properties
|
|
29
29
|
end
|
|
30
30
|
let(:instance) { double('instance', :properties => properties) }
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
subject { Attributes::Store.new(instance) }
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
it "sets default property values" do
|
|
35
35
|
subject.keys.should == properties.keys
|
|
36
36
|
subject[:default].should == 'Default'
|
|
37
37
|
end
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
it "sets default property value using mongomodel_default if defined by class" do
|
|
40
40
|
subject[:custom_default].should == CustomClassWithDefault.new("Custom class default")
|
|
41
41
|
end
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
describe "setting to nil" do
|
|
44
44
|
specify "all property types should be nullable" do
|
|
45
45
|
properties.keys.each do |property|
|
|
@@ -48,12 +48,12 @@ module MongoModel
|
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
it "sets attributes that aren't properties" do
|
|
53
53
|
subject[:non_property] = "Hello World"
|
|
54
54
|
subject[:non_property].should == "Hello World"
|
|
55
55
|
end
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
describe "type-casting" do
|
|
58
58
|
TypeCastExamples = {
|
|
59
59
|
:string =>
|
|
@@ -163,14 +163,14 @@ module MongoModel
|
|
|
163
163
|
{ :mykey => "Hello world" } => OpenStruct.new(:mykey => "Hello world")
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
TypeCastExamples.each do |type, examples|
|
|
168
168
|
context "assigning to #{type} property" do
|
|
169
169
|
examples.each do |assigned, expected|
|
|
170
170
|
if expected.is_a?(Proc)
|
|
171
171
|
it "casts #{assigned.inspect} to match proc" do
|
|
172
172
|
subject[type] = assigned
|
|
173
|
-
expected.call(subject[type]).should
|
|
173
|
+
expected.call(subject[type]).should be true
|
|
174
174
|
end
|
|
175
175
|
else
|
|
176
176
|
it "casts #{assigned.inspect} to #{expected.inspect}" do
|
|
@@ -181,24 +181,24 @@ module MongoModel
|
|
|
181
181
|
end
|
|
182
182
|
end
|
|
183
183
|
end
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
context "assigning to custom property" do
|
|
186
186
|
before(:each) do
|
|
187
187
|
@custom = CustomClass.new('instance name')
|
|
188
188
|
end
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
it "does not alter instances of CustomClass" do
|
|
191
191
|
subject[:custom] = @custom
|
|
192
192
|
subject[:custom].should == @custom
|
|
193
193
|
end
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
it "casts strings to CustomClass" do
|
|
196
196
|
subject[:custom] = "foobar"
|
|
197
197
|
subject[:custom].should == CustomClass.new('foobar')
|
|
198
198
|
end
|
|
199
199
|
end
|
|
200
200
|
end
|
|
201
|
-
|
|
201
|
+
|
|
202
202
|
describe "#before_type_cast" do
|
|
203
203
|
BeforeTypeCastExamples = {
|
|
204
204
|
:string => [ "abc", 123 ],
|
|
@@ -213,7 +213,7 @@ module MongoModel
|
|
|
213
213
|
:date => [ Date.civil(2009, 11, 15), Time.local(2008, 12, 3, 0, 0, 0, 0), "2009/3/4", "Sat Jan 01 20:15:01 UTC 2000" ],
|
|
214
214
|
:time => [ Time.local(2008, 5, 14, 1, 2, 3, 4), Date.civil(2009, 11, 15), "Sat Jan 01 20:15:01 UTC 2000", "2009/3/4" ]
|
|
215
215
|
}
|
|
216
|
-
|
|
216
|
+
|
|
217
217
|
BeforeTypeCastExamples.each do |type, examples|
|
|
218
218
|
context "assigning to #{type} property" do
|
|
219
219
|
examples.each do |example|
|
|
@@ -225,7 +225,7 @@ module MongoModel
|
|
|
225
225
|
end
|
|
226
226
|
end
|
|
227
227
|
end
|
|
228
|
-
|
|
228
|
+
|
|
229
229
|
describe "#has?" do
|
|
230
230
|
TrueExamples = {
|
|
231
231
|
:string => [ 'abc', '1' ],
|
|
@@ -241,7 +241,7 @@ module MongoModel
|
|
|
241
241
|
:openstruct => [ {} ],
|
|
242
242
|
:custom => [ CustomClass.new('foobar'), 'baz' ]
|
|
243
243
|
}
|
|
244
|
-
|
|
244
|
+
|
|
245
245
|
FalseExamples = {
|
|
246
246
|
:string => [ nil, '' ],
|
|
247
247
|
:integer => [ nil, 0 ],
|
|
@@ -256,7 +256,7 @@ module MongoModel
|
|
|
256
256
|
:openstruct => [ nil ],
|
|
257
257
|
:custom => [ nil ]
|
|
258
258
|
}
|
|
259
|
-
|
|
259
|
+
|
|
260
260
|
TrueExamples.each do |type, examples|
|
|
261
261
|
context "assigning to #{type} property" do
|
|
262
262
|
examples.each do |example|
|
|
@@ -267,7 +267,7 @@ module MongoModel
|
|
|
267
267
|
end
|
|
268
268
|
end
|
|
269
269
|
end
|
|
270
|
-
|
|
270
|
+
|
|
271
271
|
FalseExamples.each do |type, examples|
|
|
272
272
|
context "assigning to #{type} property" do
|
|
273
273
|
examples.each do |example|
|
|
@@ -279,7 +279,7 @@ module MongoModel
|
|
|
279
279
|
end
|
|
280
280
|
end
|
|
281
281
|
end
|
|
282
|
-
|
|
282
|
+
|
|
283
283
|
describe "serialization" do
|
|
284
284
|
it "converts to mongo representation" do
|
|
285
285
|
subject[:string] = 'string'
|
|
@@ -298,7 +298,7 @@ module MongoModel
|
|
|
298
298
|
subject[:as] = "As property"
|
|
299
299
|
subject[:non_property] = "Hello World"
|
|
300
300
|
subject[:custom_non_property] = CustomClass.new('custom non property')
|
|
301
|
-
|
|
301
|
+
|
|
302
302
|
subject.to_mongo.should include({
|
|
303
303
|
'string' => 'string',
|
|
304
304
|
'integer' => 42,
|
|
@@ -318,7 +318,7 @@ module MongoModel
|
|
|
318
318
|
'custom_non_property' => { :name => 'custom non property' },
|
|
319
319
|
})
|
|
320
320
|
end
|
|
321
|
-
|
|
321
|
+
|
|
322
322
|
it "loads from mongo representation" do
|
|
323
323
|
subject.from_mongo!({
|
|
324
324
|
'string' => 'string',
|
|
@@ -337,7 +337,7 @@ module MongoModel
|
|
|
337
337
|
'_custom_as' => "As property",
|
|
338
338
|
'custom_non_property' => { :name => 'custom non property' }
|
|
339
339
|
})
|
|
340
|
-
|
|
340
|
+
|
|
341
341
|
subject[:string].should == 'string'
|
|
342
342
|
subject[:integer].should == 42
|
|
343
343
|
subject[:float].should == 123.45
|
|
@@ -8,9 +8,9 @@ module MongoModel
|
|
|
8
8
|
rescue LoadError
|
|
9
9
|
require 'minitest/unit'
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
include Minitest::Assertions
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
attr_accessor :assertions
|
|
15
15
|
before(:all) { self.assertions = 0 }
|
|
16
16
|
|
|
@@ -24,10 +24,10 @@ module MongoModel
|
|
|
24
24
|
|
|
25
25
|
let(:model) { subject }
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
define_class(:TestModel, described_class)
|
|
29
29
|
subject { TestModel.new }
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
it_should_behave_like "ActiveModel"
|
|
32
32
|
end
|
|
33
33
|
end
|
|
@@ -7,47 +7,47 @@ module MongoModel
|
|
|
7
7
|
define_class(:Chapter, MongoModel::Document)
|
|
8
8
|
define_class(:IllustratedChapter, :Chapter)
|
|
9
9
|
define_class(:NonChapter, MongoModel::Document)
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
let(:klass) { Chapter }
|
|
12
12
|
let(:definition) { double(:klass => klass) }
|
|
13
13
|
let(:instance) { double }
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
subject! { Association.new(definition, instance) }
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
describe "#ensure_class" do
|
|
18
18
|
it "accepts instances of the definition class" do
|
|
19
19
|
subject.ensure_class(Chapter.new)
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
it "accepts instances of a subclass of the definition class" do
|
|
23
23
|
subject.ensure_class(IllustratedChapter.new)
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
it "raises an error if passed an object that is not an instance of the definition class" do
|
|
27
27
|
lambda {
|
|
28
28
|
subject.ensure_class(NonChapter.new)
|
|
29
29
|
}.should raise_error(MongoModel::AssociationTypeMismatch)
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
it "accepts instances of the definition class that have been reloaded" do
|
|
33
33
|
# Ensure Chapter class name is cached on the original class
|
|
34
34
|
Chapter.name
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
Object.send(:remove_const, :Chapter)
|
|
37
37
|
Object.const_set(:Chapter, Class.new(MongoModel::Document))
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
subject.ensure_class(Chapter.new)
|
|
40
40
|
end
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
it "accepts stale instances of a class that has been reloaded" do
|
|
43
43
|
chapter = Chapter.new
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
Object.send(:remove_const, :Chapter)
|
|
46
46
|
Object.const_set(:Chapter, Class.new(MongoModel::Document))
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
definition = double(:klass => Chapter)
|
|
49
49
|
association = Association.new(definition, instance)
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
association.ensure_class(chapter)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
module MongoModel
|
|
3
|
+
module MongoModel
|
|
4
4
|
specs_for(Document, EmbeddedDocument) do
|
|
5
5
|
shared_examples_for "assigning correct class to belongs_to association" do
|
|
6
6
|
define_class(:User, Document)
|
|
@@ -71,36 +71,36 @@ module MongoModel
|
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
describe "belongs_to association" do
|
|
76
76
|
define_class(:Article, described_class) do
|
|
77
77
|
belongs_to :user
|
|
78
78
|
end
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
subject { Article.new }
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
it_should_behave_like "assigning correct class to belongs_to association"
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
describe "setting a different class type" do
|
|
85
85
|
define_class(:NonUser, Document)
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
let(:non_user) { NonUser.create! }
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
it "raises a AssociationTypeMismatch exception" do
|
|
90
90
|
lambda { subject.user = non_user }.should raise_error(AssociationTypeMismatch, "User expected, got NonUser")
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
describe "#build_user" do
|
|
95
95
|
let(:user) { subject.build_user(:id => '123') }
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
it "returns a new unsaved user with the given attributes" do
|
|
98
98
|
user.should be_an_instance_of(User)
|
|
99
99
|
user.should be_a_new_record
|
|
100
100
|
user.id.should == '123'
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
describe "#create_user" do
|
|
105
105
|
it "returns a new saved user with the given attributes" do
|
|
106
106
|
user = subject.create_user(:id => '123')
|
|
@@ -110,45 +110,58 @@ module MongoModel
|
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
|
-
|
|
113
|
+
|
|
114
|
+
describe "belongs_to association with custom foreign_key" do
|
|
115
|
+
define_class(:Article, described_class) do
|
|
116
|
+
belongs_to :user, :foreign_key => :author_id
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
subject { Article.new }
|
|
120
|
+
|
|
121
|
+
it "uses the foreign key as the reference property" do
|
|
122
|
+
user = subject.build_user(:id => '123')
|
|
123
|
+
subject.author_id.should == '123'
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
114
127
|
describe "polymorphic belongs_to association" do
|
|
115
128
|
define_class(:Article, described_class) do
|
|
116
129
|
belongs_to :user, :polymorphic => true
|
|
117
130
|
end
|
|
118
|
-
|
|
131
|
+
|
|
119
132
|
subject { Article.new }
|
|
120
|
-
|
|
133
|
+
|
|
121
134
|
define_class(:NonUser, Document)
|
|
122
|
-
|
|
135
|
+
|
|
123
136
|
let(:non_user) { NonUser.create! }
|
|
124
|
-
|
|
137
|
+
|
|
125
138
|
it_should_behave_like "assigning correct class to belongs_to association"
|
|
126
|
-
|
|
139
|
+
|
|
127
140
|
describe "setting a different class type" do
|
|
128
141
|
it "sets successfully" do
|
|
129
142
|
subject.user = non_user
|
|
130
143
|
subject.user.should == non_user
|
|
131
144
|
end
|
|
132
145
|
end
|
|
133
|
-
|
|
146
|
+
|
|
134
147
|
context "when loading from database" do
|
|
135
148
|
subject { Article.new(:user => user) }
|
|
136
|
-
|
|
149
|
+
|
|
137
150
|
if specing?(EmbeddedDocument)
|
|
138
151
|
define_class(:ArticleParent, Document) do
|
|
139
152
|
property :article, Article
|
|
140
153
|
end
|
|
141
|
-
|
|
154
|
+
|
|
142
155
|
let(:parent) { ArticleParent.create!(:article => subject) }
|
|
143
156
|
let(:reloaded) { ArticleParent.find(parent.id).article }
|
|
144
157
|
else
|
|
145
158
|
before(:each) { subject.save! }
|
|
146
159
|
let(:reloaded) { Article.find(subject.id) }
|
|
147
160
|
end
|
|
148
|
-
|
|
161
|
+
|
|
149
162
|
describe "setting a different class type" do
|
|
150
163
|
subject { Article.new(:user => non_user) }
|
|
151
|
-
|
|
164
|
+
|
|
152
165
|
it "loads successfully" do
|
|
153
166
|
reloaded.user.should == non_user
|
|
154
167
|
end
|
|
@@ -6,16 +6,16 @@ module MongoModel
|
|
|
6
6
|
define_class(:MyBook, Document) do
|
|
7
7
|
has_many :chapters
|
|
8
8
|
end
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
it "defaults to :by => :foreign_key" do
|
|
11
11
|
MyBook.associations[:chapters].should be_a(Associations::HasManyByForeignKey)
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
it "sets default inverse_of value" do
|
|
15
15
|
MyBook.associations[:chapters].inverse_of.should == :my_book
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
describe "has_many :by => :foreign_key association" do
|
|
20
20
|
define_class(:Chapter, Document) do
|
|
21
21
|
belongs_to :book
|
|
@@ -25,218 +25,218 @@ module MongoModel
|
|
|
25
25
|
has_many :chapters, :by => :foreign_key, :limit => 5, :order => :id.asc
|
|
26
26
|
end
|
|
27
27
|
define_class(:NonChapter, Document)
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
let(:chapter1) { Chapter.create!(:id => '1') }
|
|
30
30
|
let(:chapter2) { IllustratedChapter.create!(:id => '2') }
|
|
31
31
|
let(:chapter3) { Chapter.create!(:id => '3') }
|
|
32
32
|
let(:nonchapter) { NonChapter.create! }
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
context "when uninitialized" do
|
|
35
35
|
subject { Book.new }
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
it "is empty" do
|
|
38
38
|
subject.chapters.should be_empty
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
shared_examples_for "accessing and manipulating a has_many :by => :foreign_key association" do
|
|
43
43
|
it "accesses chapters" do
|
|
44
44
|
subject.chapters.should include(chapter1, chapter2)
|
|
45
45
|
end
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
it "accesses chapter ids through association" do
|
|
48
48
|
subject.chapters.ids.should include(chapter1.id, chapter2.id)
|
|
49
49
|
end
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
it "adds chapters with <<" do
|
|
52
52
|
subject.chapters << chapter3
|
|
53
53
|
subject.chapters.should include(chapter1, chapter2, chapter3)
|
|
54
54
|
chapter3.book.should == subject
|
|
55
55
|
end
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
it "adds/change chapters with []=" do
|
|
58
58
|
subject.chapters[2] = chapter3
|
|
59
59
|
subject.chapters.should include(chapter1, chapter2, chapter3)
|
|
60
60
|
chapter3.book.should == subject
|
|
61
61
|
end
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
it "replaces chapters with []=" do
|
|
64
64
|
subject.chapters[1] = chapter3
|
|
65
65
|
subject.chapters.should include(chapter1, chapter3)
|
|
66
66
|
subject.chapters.should_not include(chapter2)
|
|
67
67
|
#chapter2.book.should be_nil
|
|
68
68
|
end
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
it "adds chapters with concat" do
|
|
71
71
|
subject.chapters.concat([chapter3])
|
|
72
72
|
subject.chapters.should include(chapter1, chapter2, chapter3)
|
|
73
73
|
chapter3.book.should == subject
|
|
74
74
|
end
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
it "inserts chapters" do
|
|
77
77
|
subject.chapters.insert(1, chapter3)
|
|
78
78
|
subject.chapters.should include(chapter1, chapter2, chapter3)
|
|
79
79
|
chapter3.book.should == subject
|
|
80
80
|
end
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
# it "should replace chapters" do
|
|
83
83
|
# subject.chapters.replace([chapter2, chapter3])
|
|
84
84
|
# subject.chapters.should == [chapter2, chapter3]
|
|
85
85
|
# subject.chapter_ids.should == [chapter2.id, chapter3.id]
|
|
86
86
|
# end
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
it "adds chapters with push" do
|
|
89
89
|
subject.chapters.push(chapter3)
|
|
90
90
|
subject.chapters.should include(chapter1, chapter2, chapter3)
|
|
91
91
|
chapter3.book.should == subject
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
it "adds chapters with unshift" do
|
|
95
95
|
subject.chapters.unshift(chapter3)
|
|
96
96
|
subject.chapters.should include(chapter3, chapter1, chapter2)
|
|
97
97
|
chapter3.book.should == subject
|
|
98
98
|
end
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
# it "should clear chapters" do
|
|
101
101
|
# subject.chapters.clear
|
|
102
102
|
# subject.chapters.should be_empty
|
|
103
103
|
# [chapter1, chapter2].each { |c| c.book.should be_nil }
|
|
104
104
|
# end
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
it "removes chapters with delete" do
|
|
107
107
|
subject.chapters.delete(chapter1)
|
|
108
108
|
subject.chapters.should == [chapter2]
|
|
109
109
|
chapter1.book.should be_nil
|
|
110
110
|
end
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
it "removes chapters with delete_at" do
|
|
113
113
|
subject.chapters.delete_at(0)
|
|
114
114
|
subject.chapters.should == [chapter2]
|
|
115
115
|
#chapter1.book.should be_nil
|
|
116
116
|
end
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
# it "should remove chapters with delete_if" do
|
|
119
119
|
# subject.chapters.delete_if { |c| c.id == chapter1.id }
|
|
120
120
|
# subject.chapters.should == [chapter2]
|
|
121
121
|
# subject.chapter_ids.should == [chapter2.id]
|
|
122
122
|
# end
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
it "builds a chapter" do
|
|
125
125
|
chapter4 = subject.chapters.build(:id => '4')
|
|
126
126
|
subject.chapters.should include(chapter1, chapter2, chapter4)
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
chapter4.should be_a_new_record
|
|
129
129
|
chapter4.id.should == '4'
|
|
130
130
|
chapter4.book.should == subject
|
|
131
131
|
chapter4.book_id.should == subject.id
|
|
132
132
|
end
|
|
133
|
-
|
|
133
|
+
|
|
134
134
|
it "creates a chapter" do
|
|
135
135
|
chapter4 = subject.chapters.create(:id => '4')
|
|
136
136
|
subject.chapters.should == [chapter1, chapter2, chapter4]
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
chapter4.should_not be_a_new_record
|
|
139
139
|
chapter4.id.should == '4'
|
|
140
140
|
chapter4.book.should == subject
|
|
141
141
|
chapter4.book_id.should == subject.id
|
|
142
142
|
end
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
it "finds chapters" do
|
|
145
145
|
# Create bogus chapters
|
|
146
146
|
Chapter.create!(:id => '999')
|
|
147
147
|
Chapter.create!(:id => '998')
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
result = subject.chapters.order(:id.desc)
|
|
150
150
|
result.should == [chapter2, chapter1]
|
|
151
151
|
end
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
it "finds chapters with association options" do
|
|
154
154
|
# Create bogus chapters
|
|
155
155
|
10.times { subject.chapters.create! }
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
subject.chapters.all.size.should == 5 # limit clause
|
|
158
158
|
end
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
it "supports scope select method" do
|
|
161
161
|
subject.chapters.select(:id, :_type, :book_id).should == [chapter1, chapter2]
|
|
162
162
|
end
|
|
163
|
-
|
|
163
|
+
|
|
164
164
|
it "supports array select method" do
|
|
165
165
|
subject.chapters.select { |c| c.is_a?(IllustratedChapter) }.should == [chapter2]
|
|
166
166
|
end
|
|
167
167
|
end
|
|
168
|
-
|
|
168
|
+
|
|
169
169
|
context "new instance with chapters set" do
|
|
170
170
|
subject { Book.new(:chapters => [chapter1, chapter2]) }
|
|
171
171
|
it_should_behave_like "accessing and manipulating a has_many :by => :foreign_key association"
|
|
172
172
|
end
|
|
173
|
-
|
|
173
|
+
|
|
174
174
|
context "when loaded from database" do
|
|
175
175
|
let(:book) { Book.create!(:chapters => [chapter1, chapter2]) }
|
|
176
176
|
subject { Book.find(book.id) }
|
|
177
177
|
it_should_behave_like "accessing and manipulating a has_many :by => :foreign_key association"
|
|
178
178
|
end
|
|
179
|
-
|
|
179
|
+
|
|
180
180
|
describe "with :dependent => :destroy option" do
|
|
181
181
|
define_class(:Book, Document) do
|
|
182
182
|
has_many :chapters, :by => :foreign_key, :dependent => :destroy
|
|
183
183
|
end
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
subject { Book.create!(:chapters => [chapter1, chapter2, chapter3]) }
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
context "when the parent object is destroyed" do
|
|
188
188
|
it "calls destroy on the child objects" do
|
|
189
189
|
chapter1.should_receive(:destroy)
|
|
190
190
|
chapter2.should_receive(:destroy)
|
|
191
191
|
chapter3.should_receive(:destroy)
|
|
192
|
-
|
|
192
|
+
|
|
193
193
|
subject.destroy
|
|
194
194
|
end
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
it "removes the child objects from their collection" do
|
|
197
197
|
subject.destroy
|
|
198
|
-
|
|
199
|
-
Chapter.exists?(chapter1.id).should
|
|
200
|
-
Chapter.exists?(chapter2.id).should
|
|
201
|
-
Chapter.exists?(chapter3.id).should
|
|
198
|
+
|
|
199
|
+
Chapter.exists?(chapter1.id).should be false
|
|
200
|
+
Chapter.exists?(chapter2.id).should be false
|
|
201
|
+
Chapter.exists?(chapter3.id).should be false
|
|
202
202
|
end
|
|
203
203
|
end
|
|
204
204
|
end
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
describe "with :dependent => :delete option" do
|
|
207
207
|
define_class(:Book, Document) do
|
|
208
208
|
has_many :chapters, :by => :foreign_key, :dependent => :delete
|
|
209
209
|
end
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
subject { Book.create!(:chapters => [chapter1, chapter2, chapter3]) }
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
context "when the parent object is destroyed" do
|
|
214
214
|
it "does not call destroy on the child objects" do
|
|
215
215
|
chapter1.should_not_receive(:destroy)
|
|
216
216
|
chapter2.should_not_receive(:destroy)
|
|
217
217
|
chapter3.should_not_receive(:destroy)
|
|
218
|
-
|
|
218
|
+
|
|
219
219
|
subject.destroy
|
|
220
220
|
end
|
|
221
|
-
|
|
221
|
+
|
|
222
222
|
it "removes the child objects from their collection" do
|
|
223
223
|
subject.destroy
|
|
224
|
-
|
|
225
|
-
Chapter.exists?(chapter1.id).should
|
|
226
|
-
Chapter.exists?(chapter2.id).should
|
|
227
|
-
Chapter.exists?(chapter3.id).should
|
|
224
|
+
|
|
225
|
+
Chapter.exists?(chapter1.id).should be false
|
|
226
|
+
Chapter.exists?(chapter2.id).should be false
|
|
227
|
+
Chapter.exists?(chapter3.id).should be false
|
|
228
228
|
end
|
|
229
229
|
end
|
|
230
230
|
end
|
|
231
231
|
end
|
|
232
232
|
end
|
|
233
|
-
|
|
233
|
+
|
|
234
234
|
specs_for(EmbeddedDocument) do
|
|
235
235
|
describe "defining a has_many :by => :foreign_key association" do
|
|
236
236
|
define_class(:Book, EmbeddedDocument)
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
it "raises an exception" do
|
|
239
|
-
lambda { Book.has_many :chapters, :by => :foreign_key }.should raise_error
|
|
239
|
+
lambda { Book.has_many :chapters, :by => :foreign_key }.should raise_error(RuntimeError)
|
|
240
240
|
end
|
|
241
241
|
end
|
|
242
242
|
end
|