mongoid-locomotive 2.0.0.beta9
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/MIT_LICENSE +20 -0
- data/README.rdoc +47 -0
- data/lib/mongoid.rb +141 -0
- data/lib/mongoid/associations.rb +306 -0
- data/lib/mongoid/associations/embedded_in.rb +74 -0
- data/lib/mongoid/associations/embeds_many.rb +280 -0
- data/lib/mongoid/associations/embeds_one.rb +97 -0
- data/lib/mongoid/associations/foreign_key.rb +35 -0
- data/lib/mongoid/associations/meta_data.rb +38 -0
- data/lib/mongoid/associations/options.rb +62 -0
- data/lib/mongoid/associations/proxy.rb +33 -0
- data/lib/mongoid/associations/referenced_in.rb +59 -0
- data/lib/mongoid/associations/references_many.rb +245 -0
- data/lib/mongoid/associations/references_many_as_array.rb +78 -0
- data/lib/mongoid/associations/references_one.rb +99 -0
- data/lib/mongoid/atomicity.rb +55 -0
- data/lib/mongoid/attributes.rb +242 -0
- data/lib/mongoid/callbacks.rb +21 -0
- data/lib/mongoid/collection.rb +120 -0
- data/lib/mongoid/collections.rb +71 -0
- data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
- data/lib/mongoid/collections/master.rb +29 -0
- data/lib/mongoid/collections/operations.rb +41 -0
- data/lib/mongoid/collections/slaves.rb +45 -0
- data/lib/mongoid/components.rb +34 -0
- data/lib/mongoid/config.rb +263 -0
- data/lib/mongoid/contexts.rb +24 -0
- data/lib/mongoid/contexts/enumerable.rb +156 -0
- data/lib/mongoid/contexts/ids.rb +25 -0
- data/lib/mongoid/contexts/mongo.rb +285 -0
- data/lib/mongoid/contexts/paging.rb +50 -0
- data/lib/mongoid/criteria.rb +248 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +110 -0
- data/lib/mongoid/criterion/optional.rb +189 -0
- data/lib/mongoid/cursor.rb +81 -0
- data/lib/mongoid/deprecation.rb +21 -0
- data/lib/mongoid/dirty.rb +252 -0
- data/lib/mongoid/document.rb +210 -0
- data/lib/mongoid/errors.rb +131 -0
- data/lib/mongoid/extensions.rb +115 -0
- data/lib/mongoid/extensions/array/accessors.rb +17 -0
- data/lib/mongoid/extensions/array/assimilation.rb +26 -0
- data/lib/mongoid/extensions/array/conversions.rb +23 -0
- data/lib/mongoid/extensions/array/parentization.rb +13 -0
- data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
- data/lib/mongoid/extensions/binary/conversions.rb +17 -0
- data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
- data/lib/mongoid/extensions/date/conversions.rb +24 -0
- data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
- data/lib/mongoid/extensions/false_class/equality.rb +13 -0
- data/lib/mongoid/extensions/float/conversions.rb +20 -0
- data/lib/mongoid/extensions/hash/accessors.rb +42 -0
- data/lib/mongoid/extensions/hash/assimilation.rb +40 -0
- data/lib/mongoid/extensions/hash/conversions.rb +42 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/hash/scoping.rb +12 -0
- data/lib/mongoid/extensions/integer/conversions.rb +20 -0
- data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
- data/lib/mongoid/extensions/object/conversions.rb +21 -0
- data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
- data/lib/mongoid/extensions/proc/scoping.rb +12 -0
- data/lib/mongoid/extensions/set/conversions.rb +20 -0
- data/lib/mongoid/extensions/string/conversions.rb +15 -0
- data/lib/mongoid/extensions/string/inflections.rb +97 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
- data/lib/mongoid/extensions/time_conversions.rb +35 -0
- data/lib/mongoid/extensions/true_class/equality.rb +13 -0
- data/lib/mongoid/extras.rb +61 -0
- data/lib/mongoid/factory.rb +20 -0
- data/lib/mongoid/field.rb +83 -0
- data/lib/mongoid/fields.rb +62 -0
- data/lib/mongoid/finders.rb +145 -0
- data/lib/mongoid/hierarchy.rb +74 -0
- data/lib/mongoid/identity.rb +47 -0
- data/lib/mongoid/indexes.rb +27 -0
- data/lib/mongoid/javascript.rb +21 -0
- data/lib/mongoid/javascript/functions.yml +37 -0
- data/lib/mongoid/logger.rb +19 -0
- data/lib/mongoid/matchers.rb +35 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/lib/mongoid/memoization.rb +33 -0
- data/lib/mongoid/named_scope.rb +37 -0
- data/lib/mongoid/paranoia.rb +106 -0
- data/lib/mongoid/paths.rb +61 -0
- data/lib/mongoid/persistence.rb +216 -0
- data/lib/mongoid/persistence/command.rb +39 -0
- data/lib/mongoid/persistence/insert.rb +48 -0
- data/lib/mongoid/persistence/insert_embedded.rb +44 -0
- data/lib/mongoid/persistence/remove.rb +39 -0
- data/lib/mongoid/persistence/remove_all.rb +38 -0
- data/lib/mongoid/persistence/remove_embedded.rb +50 -0
- data/lib/mongoid/persistence/update.rb +71 -0
- data/lib/mongoid/railtie.rb +67 -0
- data/lib/mongoid/railties/database.rake +60 -0
- data/lib/mongoid/scope.rb +75 -0
- data/lib/mongoid/state.rb +32 -0
- data/lib/mongoid/timestamps.rb +27 -0
- data/lib/mongoid/validations.rb +51 -0
- data/lib/mongoid/validations/associated.rb +32 -0
- data/lib/mongoid/validations/locale/en.yml +5 -0
- data/lib/mongoid/validations/uniqueness.rb +56 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/mongoid/versioning.rb +26 -0
- data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
- data/lib/rails/generators/mongoid_generator.rb +61 -0
- data/spec/integration/mongoid/association_attributes_spec.rb +71 -0
- data/spec/integration/mongoid/associations_spec.rb +768 -0
- data/spec/integration/mongoid/attributes_spec.rb +59 -0
- data/spec/integration/mongoid/callback_spec.rb +33 -0
- data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
- data/spec/integration/mongoid/criteria_spec.rb +281 -0
- data/spec/integration/mongoid/dirty_spec.rb +85 -0
- data/spec/integration/mongoid/document_spec.rb +741 -0
- data/spec/integration/mongoid/extensions_spec.rb +22 -0
- data/spec/integration/mongoid/finders_spec.rb +119 -0
- data/spec/integration/mongoid/inheritance_spec.rb +171 -0
- data/spec/integration/mongoid/named_scope_spec.rb +58 -0
- data/spec/integration/mongoid/paranoia_spec.rb +44 -0
- data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
- data/spec/integration/mongoid/persistence_spec.rb +311 -0
- data/spec/integration/mongoid/validations/uniqueness_spec.rb +206 -0
- data/spec/models/account.rb +5 -0
- data/spec/models/address.rb +40 -0
- data/spec/models/agent.rb +7 -0
- data/spec/models/animal.rb +15 -0
- data/spec/models/answer.rb +4 -0
- data/spec/models/callbacks.rb +47 -0
- data/spec/models/category.rb +13 -0
- data/spec/models/comment.rb +10 -0
- data/spec/models/country_code.rb +6 -0
- data/spec/models/employer.rb +5 -0
- data/spec/models/favorite.rb +8 -0
- data/spec/models/game.rb +9 -0
- data/spec/models/inheritance.rb +72 -0
- data/spec/models/location.rb +5 -0
- data/spec/models/login.rb +6 -0
- data/spec/models/mixed_drink.rb +4 -0
- data/spec/models/name.rb +13 -0
- data/spec/models/namespacing.rb +11 -0
- data/spec/models/paranoid_post.rb +18 -0
- data/spec/models/parents.rb +32 -0
- data/spec/models/patient.rb +15 -0
- data/spec/models/person.rb +106 -0
- data/spec/models/pet.rb +7 -0
- data/spec/models/pet_owner.rb +6 -0
- data/spec/models/phone.rb +7 -0
- data/spec/models/post.rb +25 -0
- data/spec/models/preference.rb +7 -0
- data/spec/models/question.rb +8 -0
- data/spec/models/survey.rb +6 -0
- data/spec/models/translation.rb +5 -0
- data/spec/models/user.rb +6 -0
- data/spec/models/user_accout.rb +5 -0
- data/spec/models/vet_visit.rb +5 -0
- data/spec/models/video.rb +5 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
- data/spec/unit/mongoid/associations/embeds_many_spec.rb +626 -0
- data/spec/unit/mongoid/associations/embeds_one_spec.rb +287 -0
- data/spec/unit/mongoid/associations/foreign_key_spec.rb +90 -0
- data/spec/unit/mongoid/associations/meta_data_spec.rb +110 -0
- data/spec/unit/mongoid/associations/options_spec.rb +215 -0
- data/spec/unit/mongoid/associations/referenced_in_spec.rb +145 -0
- data/spec/unit/mongoid/associations/references_many_as_array_spec.rb +424 -0
- data/spec/unit/mongoid/associations/references_many_spec.rb +502 -0
- data/spec/unit/mongoid/associations/references_one_spec.rb +204 -0
- data/spec/unit/mongoid/associations_spec.rb +688 -0
- data/spec/unit/mongoid/atomicity_spec.rb +164 -0
- data/spec/unit/mongoid/attributes_spec.rb +646 -0
- data/spec/unit/mongoid/callbacks_spec.rb +85 -0
- data/spec/unit/mongoid/collection_spec.rb +187 -0
- data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
- data/spec/unit/mongoid/collections/master_spec.rb +41 -0
- data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
- data/spec/unit/mongoid/collections_spec.rb +98 -0
- data/spec/unit/mongoid/config_spec.rb +298 -0
- data/spec/unit/mongoid/contexts/enumerable_spec.rb +447 -0
- data/spec/unit/mongoid/contexts/mongo_spec.rb +703 -0
- data/spec/unit/mongoid/contexts_spec.rb +25 -0
- data/spec/unit/mongoid/criteria_spec.rb +873 -0
- data/spec/unit/mongoid/criterion/complex_spec.rb +17 -0
- data/spec/unit/mongoid/criterion/exclusion_spec.rb +121 -0
- data/spec/unit/mongoid/criterion/inclusion_spec.rb +274 -0
- data/spec/unit/mongoid/criterion/optional_spec.rb +483 -0
- data/spec/unit/mongoid/cursor_spec.rb +80 -0
- data/spec/unit/mongoid/deprecation_spec.rb +24 -0
- data/spec/unit/mongoid/dirty_spec.rb +430 -0
- data/spec/unit/mongoid/document_spec.rb +623 -0
- data/spec/unit/mongoid/errors_spec.rb +154 -0
- data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
- data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
- data/spec/unit/mongoid/extensions/array/conversions_spec.rb +52 -0
- data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
- data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +36 -0
- data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
- data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
- data/spec/unit/mongoid/extensions/date/conversions_spec.rb +145 -0
- data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +14 -0
- data/spec/unit/mongoid/extensions/false_class/equality_spec.rb +35 -0
- data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
- data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
- data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +59 -0
- data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +35 -0
- data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
- data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
- data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
- data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +29 -0
- data/spec/unit/mongoid/extensions/object/conversions_spec.rb +44 -0
- data/spec/unit/mongoid/extensions/objectid/conversions_spec.rb +22 -0
- data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
- data/spec/unit/mongoid/extensions/set/conversions_spec.rb +21 -0
- data/spec/unit/mongoid/extensions/string/conversions_spec.rb +28 -0
- data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
- data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +107 -0
- data/spec/unit/mongoid/extensions/time_conversions_spec.rb +186 -0
- data/spec/unit/mongoid/extensions/true_class/equality_spec.rb +35 -0
- data/spec/unit/mongoid/extras_spec.rb +102 -0
- data/spec/unit/mongoid/factory_spec.rb +31 -0
- data/spec/unit/mongoid/field_spec.rb +169 -0
- data/spec/unit/mongoid/fields_spec.rb +181 -0
- data/spec/unit/mongoid/finders_spec.rb +439 -0
- data/spec/unit/mongoid/hierarchy_spec.rb +68 -0
- data/spec/unit/mongoid/identity_spec.rb +109 -0
- data/spec/unit/mongoid/indexes_spec.rb +99 -0
- data/spec/unit/mongoid/javascript_spec.rb +48 -0
- data/spec/unit/mongoid/logger_spec.rb +38 -0
- data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
- data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
- data/spec/unit/mongoid/matchers_spec.rb +329 -0
- data/spec/unit/mongoid/memoization_spec.rb +75 -0
- data/spec/unit/mongoid/named_scope_spec.rb +123 -0
- data/spec/unit/mongoid/paranoia_spec.rb +108 -0
- data/spec/unit/mongoid/paths_spec.rb +272 -0
- data/spec/unit/mongoid/persistence/insert_embedded_spec.rb +154 -0
- data/spec/unit/mongoid/persistence/insert_spec.rb +144 -0
- data/spec/unit/mongoid/persistence/remove_all_spec.rb +82 -0
- data/spec/unit/mongoid/persistence/remove_embedded_spec.rb +152 -0
- data/spec/unit/mongoid/persistence/remove_spec.rb +89 -0
- data/spec/unit/mongoid/persistence/update_spec.rb +177 -0
- data/spec/unit/mongoid/persistence_spec.rb +452 -0
- data/spec/unit/mongoid/scope_spec.rb +240 -0
- data/spec/unit/mongoid/serialization_spec.rb +43 -0
- data/spec/unit/mongoid/state_spec.rb +94 -0
- data/spec/unit/mongoid/timestamps_spec.rb +30 -0
- data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
- data/spec/unit/mongoid/validations/uniqueness_spec.rb +201 -0
- data/spec/unit/mongoid/validations_spec.rb +43 -0
- data/spec/unit/mongoid/versioning_spec.rb +41 -0
- data/spec/unit/mongoid_spec.rb +46 -0
- metadata +433 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Mongoid::Associations do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
Person.collection.remove
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context "embeds_one" do
|
|
10
|
+
|
|
11
|
+
context "with attributes hash" do
|
|
12
|
+
describe "creating associated document" do
|
|
13
|
+
let(:person) { Person.create!( :ssn => "1234", :pet_attributes => { :name => 'odie' } ) }
|
|
14
|
+
specify { person.reload.pet.name.should == 'odie' }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "updating associated document" do
|
|
18
|
+
let(:person) { Person.create!( :ssn => "1234", :pet_attributes => { :name => 'garfield' } ) }
|
|
19
|
+
before { person.update_attributes(:pet_attributes => { :name => 'odie' } ) }
|
|
20
|
+
specify { person.reload.pet.name.should == 'odie' }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "with a normal hash" do
|
|
25
|
+
describe "creating associated document" do
|
|
26
|
+
let(:person) { Person.create!( :ssn => "1234", :pet => { :name => 'odie', :tag_list => "dog, beagle" } ) }
|
|
27
|
+
specify { person.reload.pet.name.should == 'odie' }
|
|
28
|
+
specify { person.reload.pet.tags.should == ["dog", "beagle"] }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "updating associated document" do
|
|
32
|
+
let(:person) { Person.create!( :ssn => "1234", :pet => { :name => 'garfield', :tag_list => "cat" } ) }
|
|
33
|
+
before { person.update_attributes!(:pet => { :name => 'odie', :tag_list => "dog, beagle" } ) }
|
|
34
|
+
specify { person.reload.pet.name.should == 'odie' }
|
|
35
|
+
specify { person.reload.pet.tags.should == ["dog", "beagle"] }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "embeds_many" do
|
|
42
|
+
|
|
43
|
+
context "with attributes hash" do
|
|
44
|
+
describe "creating associated document" do
|
|
45
|
+
let(:person) { Person.create!( :ssn => "1234", :favorites_attributes => { '0' => { :title => 'something' } } ) }
|
|
46
|
+
specify { person.reload.favorites.first.title.should == 'something' }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "updating associated document" do
|
|
50
|
+
let(:person) { Person.create!( :ssn => "1234", :favorites => { '0' => { :title => 'nothing' } } ) }
|
|
51
|
+
before do
|
|
52
|
+
person.update_attributes(:favorites_attributes => { '0' => { :title => 'something' } } )
|
|
53
|
+
end
|
|
54
|
+
specify { person.reload.favorites.first.title.should == 'something' }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "with a normal hash" do
|
|
59
|
+
describe "creating associated document" do
|
|
60
|
+
let(:person) { Person.create!( :ssn => "1234", :favorites => { '0' => { :title => 'something' } } ) }
|
|
61
|
+
specify { person.reload.favorites.first.title.should == 'something' }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "updating associated document" do
|
|
65
|
+
let(:person) { Person.create!( :ssn => "1234", :favorites => { '0' => { :title => 'nothing' } } ) }
|
|
66
|
+
before { person.update_attributes(:favorites => { '0' => { :title => 'something' } } ) }
|
|
67
|
+
specify { person.reload.favorites.first.title.should == 'something' }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Mongoid::Associations do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
[ Artist, Person, Game, Post, Preference ].each { |klass| klass.collection.remove }
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context "anonymous extensions" do
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
@person = Person.new(:title => "Dr")
|
|
13
|
+
@address_one = Address.new(:street => "Oxford")
|
|
14
|
+
@address_two = Address.new(:street => "Bond")
|
|
15
|
+
@name = Name.new(:first_name => "Richard", :last_name => "Dawkins")
|
|
16
|
+
@person.addresses << [ @address_one, @address_two ]
|
|
17
|
+
@person.name = @name
|
|
18
|
+
@person.save
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "when defined on an embeds_many" do
|
|
22
|
+
|
|
23
|
+
it "applies the extension" do
|
|
24
|
+
addresses = @person.addresses.find_by_street("Oxford")
|
|
25
|
+
addresses.size.should == 1
|
|
26
|
+
addresses.first.should == @address_one
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "when defined on a has_one" do
|
|
31
|
+
|
|
32
|
+
it "applies the extension" do
|
|
33
|
+
name = @person.name
|
|
34
|
+
name.dawkins?.should be_true
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "when defined on an embedded_in" do
|
|
39
|
+
|
|
40
|
+
it "applies the extension" do
|
|
41
|
+
@address_two.addressable.doctor?.should be_true
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "creation of an embedded association on a callback" do
|
|
47
|
+
|
|
48
|
+
it "allows the use of create!" do
|
|
49
|
+
artist = Artist.create!(:name => "Depeche Mode")
|
|
50
|
+
artist.songs.size.should == 2
|
|
51
|
+
artist.songs.first.title.should == "0"
|
|
52
|
+
artist.songs.last.title.should == "1"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "passing a relational child to the parent constructor" do
|
|
57
|
+
|
|
58
|
+
before do
|
|
59
|
+
@game = Game.new(:score => 1)
|
|
60
|
+
@person = Person.new(:title => "Sir", :game => @game)
|
|
61
|
+
@person.save
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "sets the association on save" do
|
|
65
|
+
@from_db = Person.find(@person.id)
|
|
66
|
+
@from_db.game.should == @game
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "sets the reverse association before save" do
|
|
70
|
+
@game.person.should == @person
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "sets the reverse association after save" do
|
|
74
|
+
@from_db = Game.find(@game.id)
|
|
75
|
+
@game.person.should == @person
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "creation of an embedded association via create" do
|
|
80
|
+
|
|
81
|
+
context "when passed a parent" do
|
|
82
|
+
|
|
83
|
+
before do
|
|
84
|
+
@artist = Artist.new(:name => "Placebo")
|
|
85
|
+
@label = Label.create(:artist => @artist, :name => "Island")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "saves the parent and the child" do
|
|
89
|
+
from_db = Artist.find(@artist.id)
|
|
90
|
+
from_db.labels.first.should == @label
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "does not save the child more than once" do
|
|
94
|
+
from_db = Artist.find(@artist.id)
|
|
95
|
+
from_db.labels.size.should == 1
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "criteria on has many embedded associations" do
|
|
101
|
+
|
|
102
|
+
before do
|
|
103
|
+
@person = Person.new(:title => "Sir")
|
|
104
|
+
@sf_apartment = Address.new(:street => "Genoa Pl", :state => "CA", :address_type => "Apartment")
|
|
105
|
+
@la_home = Address.new(:street => "Rodeo Dr", :state => "CA", :address_type => "Home")
|
|
106
|
+
@sf_home = Address.new(:street => "Pacific", :state => "CA", :address_type => "Home")
|
|
107
|
+
@person.addresses << [ @sf_apartment, @la_home, @sf_home ]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "handles a single criteria" do
|
|
111
|
+
cas = @person.addresses.california
|
|
112
|
+
cas.size.should == 3
|
|
113
|
+
cas.should == [ @sf_apartment, @la_home, @sf_home ]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "handles chained criteria" do
|
|
117
|
+
ca_homes = @person.addresses.california.homes
|
|
118
|
+
ca_homes.size.should == 2
|
|
119
|
+
ca_homes.should == [ @la_home, @sf_home ]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "handles chained criteria with named scopes" do
|
|
123
|
+
ca_homes = @person.addresses.california.homes.rodeo
|
|
124
|
+
ca_homes.size.should == 1
|
|
125
|
+
ca_homes.should == [ @la_home ]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context "one-to-one relational associations" do
|
|
130
|
+
|
|
131
|
+
before do
|
|
132
|
+
@person = Person.new(:title => "Sir")
|
|
133
|
+
@game = Game.new(:score => 1)
|
|
134
|
+
@person.game = @game
|
|
135
|
+
@person.save
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "sets the association on save" do
|
|
139
|
+
@from_db = Person.find(@person.id)
|
|
140
|
+
@from_db.game.should == @game
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "sets the reverse association before save" do
|
|
144
|
+
@game.person.should == @person
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "sets the reverse association after save" do
|
|
148
|
+
@from_db = Game.find(@game.id)
|
|
149
|
+
@game.person.should == @person
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context "when defining a class name and foreign key" do
|
|
153
|
+
|
|
154
|
+
before do
|
|
155
|
+
@user = User.new(:name => "Don Julio")
|
|
156
|
+
@account = @user.account.build(:number => "1234567890")
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "sets the name of the association properly" do
|
|
160
|
+
@account.creator.should == @user
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "one-to-many relational associations" do
|
|
167
|
+
[
|
|
168
|
+
["with default naming scheme", Person, :person],
|
|
169
|
+
["with custom naming scheme and :inverse_of", User, :author],
|
|
170
|
+
["with custom naming scheme and no :inverse_of", Agent, :poster]
|
|
171
|
+
].each do |description, parent_class, association_name|
|
|
172
|
+
context description do
|
|
173
|
+
before do
|
|
174
|
+
@person = parent_class.new(:title => "Sir")
|
|
175
|
+
@post = Post.new(:title => "Testing")
|
|
176
|
+
@person.posts = [@post]
|
|
177
|
+
@person.save
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "sets the association on save" do
|
|
181
|
+
from_db = parent_class.find(@person.id)
|
|
182
|
+
from_db.posts.should == [@post]
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe "#build" do
|
|
186
|
+
|
|
187
|
+
before do
|
|
188
|
+
@another = @person.posts.build(:title => "Another")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "sets new_record to true" do
|
|
192
|
+
@another.new_record?.should == true
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe "#delete_all" do
|
|
197
|
+
|
|
198
|
+
context "without conditions" do
|
|
199
|
+
|
|
200
|
+
before do
|
|
201
|
+
@person.posts.delete_all
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "deletes all the related objects" do
|
|
205
|
+
Post.count.should == 0
|
|
206
|
+
@person.posts.size.should == 0
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
context "with conditions" do
|
|
211
|
+
|
|
212
|
+
before do
|
|
213
|
+
@person.posts.delete_all(:conditions => { :title => "Testing" })
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "deletes the appropriate objects" do
|
|
217
|
+
Post.count.should == 0
|
|
218
|
+
@person.posts.size.should == 0
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
describe "#destroy_all" do
|
|
224
|
+
|
|
225
|
+
context "without conditions" do
|
|
226
|
+
|
|
227
|
+
before do
|
|
228
|
+
@person.posts.destroy_all
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "deletes all the related objects" do
|
|
232
|
+
Post.count.should == 0
|
|
233
|
+
@person.posts.size.should == 0
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
context "with conditions" do
|
|
238
|
+
|
|
239
|
+
before do
|
|
240
|
+
@person.posts.destroy_all(:conditions => { :title => "Testing" })
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "deletes the appropriate objects" do
|
|
244
|
+
Post.count.should == 0
|
|
245
|
+
@person.posts.size.should == 0
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context "when adding a new association" do
|
|
251
|
+
|
|
252
|
+
before do
|
|
253
|
+
@new_post = Post.new(:title => "New")
|
|
254
|
+
@person.posts << @new_post
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it "rememoizes the new association" do
|
|
258
|
+
@person.posts.should == [ @post, @new_post ]
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
context "when building" do
|
|
263
|
+
|
|
264
|
+
before do
|
|
265
|
+
@person = parent_class.new(:title => "Mr")
|
|
266
|
+
@post = @person.posts.build(:title => "First")
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "sets the reverse association" do
|
|
270
|
+
@post.send(association_name).should == @person
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
context "finding associated objects" do
|
|
276
|
+
|
|
277
|
+
before do
|
|
278
|
+
@extra_post = Post.create(:title => "Orphan")
|
|
279
|
+
@from_db = parent_class.find(@person.id)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
context "finding all" do
|
|
283
|
+
|
|
284
|
+
it "returns only those objects scoped to the parent" do
|
|
285
|
+
Post.all.size.should == 2
|
|
286
|
+
@from_db.posts.all.size.should == 1
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
context "finding with conditions" do
|
|
292
|
+
|
|
293
|
+
context "finding all" do
|
|
294
|
+
|
|
295
|
+
it "returns only those objects scoped to the parent" do
|
|
296
|
+
posts = @from_db.posts.find(:all, :conditions => { :title => "Testing" })
|
|
297
|
+
posts.size.should == 1
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
context "finding first" do
|
|
303
|
+
|
|
304
|
+
it "returns only those objects scoped to the parent" do
|
|
305
|
+
post = @from_db.posts.find(:first, :conditions => { :title => "Testing" })
|
|
306
|
+
post.should == @post
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
context "finding last" do
|
|
312
|
+
|
|
313
|
+
it "returns only those objects scoped to the parent" do
|
|
314
|
+
post = @from_db.posts.find(:last, :conditions => { :title => "Testing" })
|
|
315
|
+
post.should == @post
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
context "using a named scope" do
|
|
321
|
+
|
|
322
|
+
before do
|
|
323
|
+
@post.created_at = 15.days.ago
|
|
324
|
+
@post.save
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it "returns only those scoped to the parent plus the named scope" do
|
|
328
|
+
posts = @from_db.posts.recent
|
|
329
|
+
posts.size.should == 1
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
context "using a criteria class method" do
|
|
335
|
+
|
|
336
|
+
before do
|
|
337
|
+
@post.created_at = 45.days.ago
|
|
338
|
+
@post.save
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it "returns only those scoped to the parent plus the named scope" do
|
|
342
|
+
posts = @from_db.posts.old
|
|
343
|
+
posts.size.should == 1
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
context "calling criteria methods" do
|
|
349
|
+
|
|
350
|
+
before do
|
|
351
|
+
@post.title = "New Title"
|
|
352
|
+
@post.save
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it "returns the proper object for the criteria" do
|
|
356
|
+
posts = @from_db.posts.where(:title => "New Title")
|
|
357
|
+
posts.size.should == 1
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
context "when calling with a new criteria" do
|
|
361
|
+
|
|
362
|
+
before do
|
|
363
|
+
@from_db.posts.create(:title => "Other Title")
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
it "does not retain the old criteria" do
|
|
367
|
+
@from_db.posts.where(:title => "New Title").size.should == 1
|
|
368
|
+
@from_db.posts.size.should == 2
|
|
369
|
+
@from_db.posts.where(:title => "Other Title").size.should == 1
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
context "nested embedded associations" do
|
|
380
|
+
|
|
381
|
+
before do
|
|
382
|
+
@person = Person.create(:title => "Mr")
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
context "having an embedded document as both an embeds_one and many" do
|
|
386
|
+
|
|
387
|
+
before do
|
|
388
|
+
@agent = Agent.new(:number => "007")
|
|
389
|
+
@person = Person.new(:title => "Dr", :ssn => "123-12-6666")
|
|
390
|
+
@agent_name = Name.new(:first_name => "James")
|
|
391
|
+
@person_name = Name.new(:first_name => "Jack")
|
|
392
|
+
@agent.names << @agent_name
|
|
393
|
+
@person.name = @person_name
|
|
394
|
+
@agent.save
|
|
395
|
+
@person.save
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
context "when the document is an embeds_one" do
|
|
399
|
+
|
|
400
|
+
it "sets the association_name" do
|
|
401
|
+
@agent_name.namable = @agent
|
|
402
|
+
@agent_name.namable.should == @agent
|
|
403
|
+
@agent_name.association_name.should == "names"
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
context "when the document is an embeds_many" do
|
|
408
|
+
|
|
409
|
+
it "sets the association_name" do
|
|
410
|
+
@person_name.namable = @person
|
|
411
|
+
@person_name.namable.should == @person
|
|
412
|
+
@person_name.association_name.should == "name"
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
context "saving an existing parent document with existing children" do
|
|
418
|
+
|
|
419
|
+
before do
|
|
420
|
+
@address = @person.addresses.create(:street => "Oxford St")
|
|
421
|
+
@address.city = "London"
|
|
422
|
+
@person.save
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
it "saves all dirty children" do
|
|
426
|
+
from_db = Person.find(@person.id)
|
|
427
|
+
from_db.addresses.first.city.should == "London"
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
context "saving an existing parent document with new children" do
|
|
432
|
+
|
|
433
|
+
context "when building" do
|
|
434
|
+
|
|
435
|
+
before do
|
|
436
|
+
@address = @person.addresses.build(:street => "Oxford St")
|
|
437
|
+
@person.save
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
it "saves all new children" do
|
|
441
|
+
from_db = Person.find(@person.id)
|
|
442
|
+
from_db.addresses.first.should == @address
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
context "when appending one elements" do
|
|
447
|
+
|
|
448
|
+
before do
|
|
449
|
+
@address = Address.new(:street => "Oxford St")
|
|
450
|
+
@person.addresses << @address
|
|
451
|
+
@person.save
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it "saves all new children" do
|
|
455
|
+
from_db = Person.find(@person.id)
|
|
456
|
+
from_db.addresses.first.should == @address
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
context "when appending several elements" do
|
|
461
|
+
|
|
462
|
+
before do
|
|
463
|
+
@address = Address.new(:street => "Oxford St")
|
|
464
|
+
@address2 = Address.new(:street => "Cambridge St")
|
|
465
|
+
@person.addresses << @address
|
|
466
|
+
@person.addresses << @address2
|
|
467
|
+
@person.save
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it "saves all new children" do
|
|
471
|
+
from_db = Person.find(@person.id)
|
|
472
|
+
from_db.addresses.count.should == 2
|
|
473
|
+
from_db.addresses.first.should == @address
|
|
474
|
+
from_db.addresses.second.should == @address2
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
context "when creating" do
|
|
479
|
+
|
|
480
|
+
before do
|
|
481
|
+
@address = @person.addresses.create(:street => "Oxford St")
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
it "saves all new children" do
|
|
485
|
+
@person.reload.addresses.first.should == @address
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
context "when overwriting" do
|
|
490
|
+
before do
|
|
491
|
+
@person.addresses.build(:street => "Oxford St")
|
|
492
|
+
@person.addresses = @person.addresses
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it "still recognizes the embedded document as a new record" do
|
|
496
|
+
@person.addresses.first.should be_new_record
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
context "when overwriting with nil" do
|
|
501
|
+
before do
|
|
502
|
+
@person.addresses = nil
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
it "sets the association to an empty array" do
|
|
506
|
+
@person.addresses.should == []
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
context "one level nested" do
|
|
513
|
+
|
|
514
|
+
before do
|
|
515
|
+
@address = @person.addresses.create(:street => "Oxford St")
|
|
516
|
+
@name = @person.create_name(:first_name => "Gordon")
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it "persists all the associations properly" do
|
|
520
|
+
@name.last_name = "Brown"
|
|
521
|
+
@person.name.last_name.should == "Brown"
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
it "sets the new_record values properly" do
|
|
525
|
+
from_db = Person.find(@person.id)
|
|
526
|
+
new_name = from_db.create_name(:first_name => "Flash")
|
|
527
|
+
new_name.new_record?.should be_false
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
context "updating embedded arrays" do
|
|
531
|
+
|
|
532
|
+
before do
|
|
533
|
+
@person.addresses.create(:street => "Picadilly Circus")
|
|
534
|
+
@from_db = Person.find(@person.id)
|
|
535
|
+
@first = @from_db.addresses[0]
|
|
536
|
+
@second = @from_db.addresses[1]
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
it "does not change the internal order of the array" do
|
|
540
|
+
@from_db.addresses.first.update_attributes(:city => "London")
|
|
541
|
+
@from_db.addresses.should == [ @first, @second ]
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
it "does not change the internal order of the attributes in the parent" do
|
|
545
|
+
@from_db.addresses.first.update_attributes(:city => "London")
|
|
546
|
+
@from_db.attributes["addresses"].should == [@first.attributes, @second.attributes]
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
context "updating an element that is a new record" do
|
|
550
|
+
before do
|
|
551
|
+
@third = Address.new(:street => "Foo")
|
|
552
|
+
@fourth = Address.new(:street => "Bar")
|
|
553
|
+
@from_db.addresses << @third
|
|
554
|
+
@from_db.addresses << @fourth
|
|
555
|
+
@from_db.save!
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
it "does not change the internal order of the array" do
|
|
559
|
+
@third.update_attributes(:city => "London")
|
|
560
|
+
@from_db.addresses.should == [ @first, @second, @third, @fourth ]
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
it "does not change the internal order of the attributes in the parent" do
|
|
564
|
+
@third.update_attributes(:city => "London")
|
|
565
|
+
@from_db.attributes["addresses"].should == [@first.attributes, @second.attributes, @third.attributes, @fourth.attributes]
|
|
566
|
+
end
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
describe "#first" do
|
|
571
|
+
|
|
572
|
+
let(:person) do
|
|
573
|
+
Person.create(:ssn => "444-33-7777")
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
before do
|
|
577
|
+
@video_id = person.videos.create(:title => "Oldboy").id
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
it "does not generate a new id each time" do
|
|
581
|
+
5.times { person.videos.first.id.should == @video_id }
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
describe "#delete_all" do
|
|
586
|
+
|
|
587
|
+
it "removes the appropriate documents" do
|
|
588
|
+
@person.addresses.delete_all(:conditions => { :street => "Oxford St" }).should == 1
|
|
589
|
+
@person.addresses.size.should == 0
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
describe "#destroy_all" do
|
|
594
|
+
|
|
595
|
+
it "removes the appropriate documents" do
|
|
596
|
+
@person.addresses.destroy_all(:conditions => { :street => "Oxford St" }).should == 1
|
|
597
|
+
@person.addresses.size.should == 0
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
context "embedded_in instantiated and added later to parent" do
|
|
603
|
+
before do
|
|
604
|
+
@address = Address.new
|
|
605
|
+
@person = Person.new
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
it "doesn't memoize a nil parent" do
|
|
609
|
+
@address.addressable
|
|
610
|
+
@person.addresses << @address
|
|
611
|
+
@address.addressable.should == @person
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
context "multiple levels nested" do
|
|
616
|
+
|
|
617
|
+
context "when a has-many to has_one" do
|
|
618
|
+
|
|
619
|
+
before do
|
|
620
|
+
@person.phone_numbers.create(:number => "4155551212")
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
it "persists all the associations properly" do
|
|
624
|
+
from_db = Person.find(@person.id)
|
|
625
|
+
phone = from_db.phone_numbers.first
|
|
626
|
+
phone.create_country_code(:code => 1)
|
|
627
|
+
from_db.phone_numbers.first.country_code.code.should == 1
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
context "when a has-one to has-many" do
|
|
633
|
+
|
|
634
|
+
before do
|
|
635
|
+
@person = Person.new(:title => "Sir", :ssn => "1")
|
|
636
|
+
@name = Name.new(:first_name => "Syd")
|
|
637
|
+
@person.name = @name
|
|
638
|
+
@person.save
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
it "persists all the associations properly" do
|
|
642
|
+
from_db = Person.find(@person.id)
|
|
643
|
+
translation = Translation.new(:language => "fr")
|
|
644
|
+
from_db.name.translations << translation
|
|
645
|
+
from_db.attributes[:name][:translations].should_not be_nil
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
context "when a has-many to has-many" do
|
|
651
|
+
|
|
652
|
+
before do
|
|
653
|
+
@address = Address.new(:street => "Upper Street")
|
|
654
|
+
@person.addresses << @address
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
it "bubbles the child association up to root" do
|
|
658
|
+
location = Location.new(:name => "Home")
|
|
659
|
+
@address.locations << location
|
|
660
|
+
location.stubs(:valid?).returns(false)
|
|
661
|
+
@person.save
|
|
662
|
+
@person.addresses.first.locations.first.should == location
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
context "references many as array" do
|
|
669
|
+
|
|
670
|
+
context "with a saved parent" do
|
|
671
|
+
|
|
672
|
+
before do
|
|
673
|
+
@person = Person.create!(:ssn => "992-33-1010")
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
context "appending a new document" do
|
|
677
|
+
|
|
678
|
+
before do
|
|
679
|
+
@preference = Preference.new(:name => "test")
|
|
680
|
+
@person.preferences << @preference
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
it "adds the document to the array" do
|
|
684
|
+
@person.preferences.first.should == @preference
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
it "adds the parent document to the reverse association" do
|
|
688
|
+
@preference.people.first.should == @person
|
|
689
|
+
end
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
context "building a document" do
|
|
693
|
+
|
|
694
|
+
before do
|
|
695
|
+
@preference = @person.preferences.build(:name => "test")
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
it "adds the document to the array" do
|
|
699
|
+
@person.preferences.first.should == @preference
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
it "adds the parent document to the reverse association" do
|
|
703
|
+
@preference.people.first.should == @person
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
context "creating a document" do
|
|
708
|
+
|
|
709
|
+
before do
|
|
710
|
+
@preference = @person.preferences.create(:name => "test")
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
it "adds the document to the array" do
|
|
714
|
+
@person.preferences.first.should == @preference
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
it "adds the parent document to the reverse association" do
|
|
718
|
+
@preference.people.first.should == @person
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
context "with a new parent" do
|
|
724
|
+
|
|
725
|
+
let(:person) do
|
|
726
|
+
Person.new(:ssn => "992-33-1010")
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
context "appending a new document" do
|
|
730
|
+
|
|
731
|
+
before do
|
|
732
|
+
@preference = Preference.new(:name => "test")
|
|
733
|
+
person.preferences << @preference
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
it "adds the document to the array" do
|
|
737
|
+
person.preferences.first.should == @preference
|
|
738
|
+
end
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
context "building a document" do
|
|
742
|
+
|
|
743
|
+
before do
|
|
744
|
+
@preference = person.preferences.build(:name => "test")
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
it "adds the document to the array" do
|
|
748
|
+
person.preferences.first.should == @preference
|
|
749
|
+
end
|
|
750
|
+
|
|
751
|
+
it "adds the parent document to the reverse association"
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
context "creating a document" do
|
|
755
|
+
|
|
756
|
+
before do
|
|
757
|
+
@preference = person.preferences.create(:name => "test")
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
it "adds the document to the array" do
|
|
761
|
+
person.preferences.first.should == @preference
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
it "adds the parent document to the reverse association"
|
|
765
|
+
end
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
end
|