sbf-dm-core 1.3.0.beta
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 +7 -0
- data/.autotest +29 -0
- data/.document +5 -0
- data/.gitignore +44 -0
- data/.rspec +1 -0
- data/.rubocop.yml +468 -0
- data/.travis.yml +57 -0
- data/.yardopts +1 -0
- data/Gemfile +70 -0
- data/LICENSE +20 -0
- data/README.md +269 -0
- data/Rakefile +4 -0
- data/dm-core.gemspec +21 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +233 -0
- data/lib/dm-core/adapters/in_memory_adapter.rb +110 -0
- data/lib/dm-core/adapters.rb +249 -0
- data/lib/dm-core/associations/many_to_many.rb +477 -0
- data/lib/dm-core/associations/many_to_one.rb +282 -0
- data/lib/dm-core/associations/one_to_many.rb +332 -0
- data/lib/dm-core/associations/one_to_one.rb +84 -0
- data/lib/dm-core/associations/relationship.rb +650 -0
- data/lib/dm-core/backwards.rb +11 -0
- data/lib/dm-core/collection.rb +1486 -0
- data/lib/dm-core/core_ext/kernel.rb +21 -0
- data/lib/dm-core/core_ext/pathname.rb +4 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +6 -0
- data/lib/dm-core/model/hook.rb +99 -0
- data/lib/dm-core/model/is.rb +30 -0
- data/lib/dm-core/model/property.rb +244 -0
- data/lib/dm-core/model/relationship.rb +366 -0
- data/lib/dm-core/model/scope.rb +87 -0
- data/lib/dm-core/model.rb +876 -0
- data/lib/dm-core/property/binary.rb +19 -0
- data/lib/dm-core/property/boolean.rb +35 -0
- data/lib/dm-core/property/class.rb +23 -0
- data/lib/dm-core/property/date.rb +45 -0
- data/lib/dm-core/property/date_time.rb +44 -0
- data/lib/dm-core/property/decimal.rb +47 -0
- data/lib/dm-core/property/discriminator.rb +40 -0
- data/lib/dm-core/property/float.rb +27 -0
- data/lib/dm-core/property/integer.rb +32 -0
- data/lib/dm-core/property/invalid_value_error.rb +17 -0
- data/lib/dm-core/property/lookup.rb +26 -0
- data/lib/dm-core/property/numeric.rb +35 -0
- data/lib/dm-core/property/object.rb +33 -0
- data/lib/dm-core/property/serial.rb +13 -0
- data/lib/dm-core/property/string.rb +47 -0
- data/lib/dm-core/property/text.rb +12 -0
- data/lib/dm-core/property/time.rb +46 -0
- data/lib/dm-core/property/typecast/numeric.rb +32 -0
- data/lib/dm-core/property/typecast/time.rb +33 -0
- data/lib/dm-core/property.rb +856 -0
- data/lib/dm-core/property_set.rb +177 -0
- data/lib/dm-core/query/conditions/comparison.rb +886 -0
- data/lib/dm-core/query/conditions/operation.rb +710 -0
- data/lib/dm-core/query/direction.rb +33 -0
- data/lib/dm-core/query/operator.rb +34 -0
- data/lib/dm-core/query/path.rb +113 -0
- data/lib/dm-core/query/sort.rb +38 -0
- data/lib/dm-core/query.rb +1352 -0
- data/lib/dm-core/relationship_set.rb +69 -0
- data/lib/dm-core/repository.rb +226 -0
- data/lib/dm-core/resource/persistence_state/clean.rb +36 -0
- data/lib/dm-core/resource/persistence_state/deleted.rb +26 -0
- data/lib/dm-core/resource/persistence_state/dirty.rb +91 -0
- data/lib/dm-core/resource/persistence_state/immutable.rb +32 -0
- data/lib/dm-core/resource/persistence_state/persisted.rb +25 -0
- data/lib/dm-core/resource/persistence_state/transient.rb +87 -0
- data/lib/dm-core/resource/persistence_state.rb +70 -0
- data/lib/dm-core/resource.rb +1220 -0
- data/lib/dm-core/spec/lib/adapter_helpers.rb +63 -0
- data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
- data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
- data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
- data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
- data/lib/dm-core/spec/setup.rb +164 -0
- data/lib/dm-core/spec/shared/adapter_spec.rb +366 -0
- data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
- data/lib/dm-core/spec/shared/resource_spec.rb +1221 -0
- data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
- data/lib/dm-core/spec/shared/semipublic/property_spec.rb +184 -0
- data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/chainable.rb +18 -0
- data/lib/dm-core/support/deprecate.rb +12 -0
- data/lib/dm-core/support/descendant_set.rb +89 -0
- data/lib/dm-core/support/equalizer.rb +48 -0
- data/lib/dm-core/support/ext/array.rb +22 -0
- data/lib/dm-core/support/ext/blank.rb +25 -0
- data/lib/dm-core/support/ext/hash.rb +67 -0
- data/lib/dm-core/support/ext/module.rb +47 -0
- data/lib/dm-core/support/ext/object.rb +57 -0
- data/lib/dm-core/support/ext/string.rb +24 -0
- data/lib/dm-core/support/ext/try_dup.rb +12 -0
- data/lib/dm-core/support/hook.rb +388 -0
- data/lib/dm-core/support/inflections.rb +60 -0
- data/lib/dm-core/support/inflector/inflections.rb +211 -0
- data/lib/dm-core/support/inflector/methods.rb +151 -0
- data/lib/dm-core/support/lazy_array.rb +451 -0
- data/lib/dm-core/support/local_object_space.rb +13 -0
- data/lib/dm-core/support/logger.rb +201 -0
- data/lib/dm-core/support/mash.rb +176 -0
- data/lib/dm-core/support/naming_conventions.rb +109 -0
- data/lib/dm-core/support/ordered_set.rb +381 -0
- data/lib/dm-core/support/subject.rb +33 -0
- data/lib/dm-core/support/subject_set.rb +251 -0
- data/lib/dm-core/version.rb +3 -0
- data/lib/dm-core.rb +274 -0
- data/script/performance.rb +275 -0
- data/script/profile.rb +218 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
- data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +69 -0
- data/spec/public/associations/many_to_many_spec.rb +197 -0
- data/spec/public/associations/many_to_one_spec.rb +83 -0
- data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
- data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
- data/spec/public/associations/one_to_many_spec.rb +81 -0
- data/spec/public/associations/one_to_one_spec.rb +176 -0
- data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
- data/spec/public/collection_spec.rb +69 -0
- data/spec/public/finalize_spec.rb +77 -0
- data/spec/public/model/hook_spec.rb +245 -0
- data/spec/public/model/property_spec.rb +91 -0
- data/spec/public/model/relationship_spec.rb +1040 -0
- data/spec/public/model_spec.rb +456 -0
- data/spec/public/property/binary_spec.rb +43 -0
- data/spec/public/property/boolean_spec.rb +21 -0
- data/spec/public/property/class_spec.rb +27 -0
- data/spec/public/property/date_spec.rb +21 -0
- data/spec/public/property/date_time_spec.rb +21 -0
- data/spec/public/property/decimal_spec.rb +23 -0
- data/spec/public/property/discriminator_spec.rb +134 -0
- data/spec/public/property/float_spec.rb +22 -0
- data/spec/public/property/integer_spec.rb +22 -0
- data/spec/public/property/object_spec.rb +117 -0
- data/spec/public/property/serial_spec.rb +22 -0
- data/spec/public/property/string_spec.rb +21 -0
- data/spec/public/property/text_spec.rb +62 -0
- data/spec/public/property/time_spec.rb +21 -0
- data/spec/public/property_spec.rb +333 -0
- data/spec/public/resource/state_spec.rb +72 -0
- data/spec/public/resource_spec.rb +289 -0
- data/spec/public/sel_spec.rb +53 -0
- data/spec/public/setup_spec.rb +145 -0
- data/spec/public/shared/association_collection_shared_spec.rb +309 -0
- data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
- data/spec/public/shared/collection_shared_spec.rb +1637 -0
- data/spec/public/shared/finder_shared_spec.rb +1647 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
- data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
- data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
- data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
- data/spec/semipublic/associations/relationship_spec.rb +200 -0
- data/spec/semipublic/associations_spec.rb +177 -0
- data/spec/semipublic/collection_spec.rb +110 -0
- data/spec/semipublic/model_spec.rb +96 -0
- data/spec/semipublic/property/binary_spec.rb +13 -0
- data/spec/semipublic/property/boolean_spec.rb +47 -0
- data/spec/semipublic/property/class_spec.rb +33 -0
- data/spec/semipublic/property/date_spec.rb +43 -0
- data/spec/semipublic/property/date_time_spec.rb +46 -0
- data/spec/semipublic/property/decimal_spec.rb +83 -0
- data/spec/semipublic/property/discriminator_spec.rb +19 -0
- data/spec/semipublic/property/float_spec.rb +82 -0
- data/spec/semipublic/property/integer_spec.rb +82 -0
- data/spec/semipublic/property/lookup_spec.rb +29 -0
- data/spec/semipublic/property/serial_spec.rb +13 -0
- data/spec/semipublic/property/string_spec.rb +13 -0
- data/spec/semipublic/property/text_spec.rb +31 -0
- data/spec/semipublic/property/time_spec.rb +50 -0
- data/spec/semipublic/property_spec.rb +114 -0
- data/spec/semipublic/query/conditions/comparison_spec.rb +1502 -0
- data/spec/semipublic/query/conditions/operation_spec.rb +1296 -0
- data/spec/semipublic/query/path_spec.rb +471 -0
- data/spec/semipublic/query_spec.rb +3665 -0
- data/spec/semipublic/resource/state/clean_spec.rb +89 -0
- data/spec/semipublic/resource/state/deleted_spec.rb +79 -0
- data/spec/semipublic/resource/state/dirty_spec.rb +163 -0
- data/spec/semipublic/resource/state/immutable_spec.rb +107 -0
- data/spec/semipublic/resource/state/transient_spec.rb +163 -0
- data/spec/semipublic/resource/state_spec.rb +230 -0
- data/spec/semipublic/resource_spec.rb +23 -0
- data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +198 -0
- data/spec/semipublic/shared/resource_state_shared_spec.rb +91 -0
- data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/core_ext/hash.rb +10 -0
- data/spec/support/core_ext/inheritable_attributes.rb +46 -0
- data/spec/support/properties/huge_integer.rb +17 -0
- data/spec/unit/array_spec.rb +23 -0
- data/spec/unit/blank_spec.rb +73 -0
- data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
- data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
- data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
- data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
- data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
- data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
- data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
- data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
- data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
- data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
- data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
- data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
- data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
- data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
- data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
- data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
- data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
- data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
- data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
- data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
- data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
- data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
- data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
- data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
- data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
- data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
- data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
- data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
- data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
- data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
- data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
- data/spec/unit/hash_spec.rb +27 -0
- data/spec/unit/hook_spec.rb +1216 -0
- data/spec/unit/inflections_spec.rb +14 -0
- data/spec/unit/lazy_array_spec.rb +1949 -0
- data/spec/unit/mash_spec.rb +289 -0
- data/spec/unit/module_spec.rb +70 -0
- data/spec/unit/object_spec.rb +38 -0
- data/spec/unit/try_dup_spec.rb +46 -0
- data/tasks/ci.rake +1 -0
- data/tasks/spec.rake +18 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +323 -0
|
@@ -0,0 +1,1040 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
|
|
3
|
+
class ::Car
|
|
4
|
+
include DataMapper::Resource
|
|
5
|
+
|
|
6
|
+
property :id, Serial
|
|
7
|
+
property :name, String
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class ::Engine
|
|
11
|
+
include DataMapper::Resource
|
|
12
|
+
|
|
13
|
+
property :id, Serial
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class ::Door
|
|
17
|
+
include DataMapper::Resource
|
|
18
|
+
|
|
19
|
+
property :id, Serial
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class ::Window
|
|
23
|
+
include DataMapper::Resource
|
|
24
|
+
|
|
25
|
+
property :id, Serial
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
shared_examples 'it creates a one accessor' do
|
|
29
|
+
describe 'accessor' do
|
|
30
|
+
describe 'when there is no associated resource' do
|
|
31
|
+
describe 'without a query' do
|
|
32
|
+
before :all do
|
|
33
|
+
@return = @car.__send__(@name)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'returns nil' do
|
|
37
|
+
expect(@return).to be_nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe 'with a query' do
|
|
42
|
+
before :all do
|
|
43
|
+
@return = @car.__send__(@name, id: 99)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'returns nil' do
|
|
47
|
+
expect(@return).to be_nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe 'when there is an associated resource' do
|
|
53
|
+
before :all do
|
|
54
|
+
@expected = @model.new
|
|
55
|
+
@car.__send__("#{@name}=", @expected)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe 'without a query' do
|
|
59
|
+
before :all do
|
|
60
|
+
@return = @car.__send__(@name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'returns a Resource' do
|
|
64
|
+
expect(@return).to be_kind_of(DataMapper::Resource)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'returns the expected Resource' do
|
|
68
|
+
expect(@return).to equal(@expected)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe 'with a query' do
|
|
73
|
+
before :all do
|
|
74
|
+
@car.save # save @car and @expected to set @expected.id
|
|
75
|
+
|
|
76
|
+
expect(@expected.id).not_to be_nil
|
|
77
|
+
|
|
78
|
+
@return = @car.__send__(@name, id: @expected.id)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'returns a Resource' do
|
|
82
|
+
expect(@return).to be_kind_of(DataMapper::Resource)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'returns the expected Resource' do
|
|
86
|
+
expect(@return).to eq @expected
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe 'when the target model is scoped' do
|
|
92
|
+
before :all do
|
|
93
|
+
@resource = @model.new
|
|
94
|
+
@car.__send__("#{@name}=", @resource)
|
|
95
|
+
@car.save
|
|
96
|
+
|
|
97
|
+
# set the model scope to not match the expected resource
|
|
98
|
+
@model.default_scope.update(:id.not => @resource.id)
|
|
99
|
+
|
|
100
|
+
@return = @car.model.get!(*@car.key).__send__(@name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'returns nil' do
|
|
104
|
+
expect(@return).to be_nil
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
shared_examples 'it creates a one mutator' do
|
|
111
|
+
describe 'mutator' do
|
|
112
|
+
describe 'when setting a Resource' do
|
|
113
|
+
before :all do
|
|
114
|
+
@expected = @model.new
|
|
115
|
+
|
|
116
|
+
@return = @car.__send__("#{@name}=", @expected)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'returns the expected Resource' do
|
|
120
|
+
expect(@return).to equal(@expected)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'sets the Resource' do
|
|
124
|
+
expect(@car.__send__(@name)).to equal(@expected)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'relates associated Resource' do
|
|
128
|
+
relationship = Car.relationships[@name]
|
|
129
|
+
many_to_one = relationship.is_a?(DataMapper::Associations::ManyToOne::Relationship)
|
|
130
|
+
one_to_one_through = relationship.is_a?(DataMapper::Associations::OneToOne::Relationship) && relationship.respond_to?(:through)
|
|
131
|
+
|
|
132
|
+
pending if many_to_one || one_to_one_through
|
|
133
|
+
|
|
134
|
+
expect(@expected.car).to eq @car
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'persists the Resource' do
|
|
138
|
+
expect(@car.save).to be(true)
|
|
139
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to eq @expected
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'persists the associated Resource' do
|
|
143
|
+
expect(@car.save).to be(true)
|
|
144
|
+
expect(@expected).to be_saved
|
|
145
|
+
expect(@expected.model.get!(*@expected.key).car).to eq @car
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe 'when setting a Hash' do
|
|
150
|
+
before :all do
|
|
151
|
+
@car.__send__("#{@name}=", @model.new)
|
|
152
|
+
|
|
153
|
+
attributes = {id: 10}
|
|
154
|
+
@expected = @model.new(attributes)
|
|
155
|
+
|
|
156
|
+
@return = @car.__send__("#{@name}=", attributes)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'returns the expected Resource' do
|
|
160
|
+
expect(@return).to eq @expected
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'sets the Resource' do
|
|
164
|
+
expect(@car.__send__(@name)).to equal(@return)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
relationship = Car.relationships[@name]
|
|
168
|
+
many_to_one = relationship.is_a?(DataMapper::Associations::ManyToOne::Relationship)
|
|
169
|
+
it 'relates associated Resource' do
|
|
170
|
+
one_to_one_through = relationship.is_a?(DataMapper::Associations::OneToOne::Relationship) && relationship.respond_to?(:through)
|
|
171
|
+
|
|
172
|
+
pending if many_to_one || one_to_one_through
|
|
173
|
+
expect(@return.car).to eq @car
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'persists the Resource' do
|
|
177
|
+
expect(@car.save).to be(true)
|
|
178
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to eq @return
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'persists the associated Resource' do
|
|
182
|
+
expect(@car.save).to be(true)
|
|
183
|
+
expect(@return).to be_saved
|
|
184
|
+
expect(@return&.model&.get!(*@return&.key).car).to eq @car
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
describe 'when setting nil' do
|
|
189
|
+
before :all do
|
|
190
|
+
@car.__send__("#{@name}=", @model.new)
|
|
191
|
+
|
|
192
|
+
@return = @car.__send__("#{@name}=", nil)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'returns nil' do
|
|
196
|
+
expect(@return).to be_nil
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'sets nil' do
|
|
200
|
+
expect(@car.__send__(@name)).to be_nil
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'persists as nil' do
|
|
204
|
+
expect(@car.save).to be(true)
|
|
205
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to be_nil
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
describe 'when changing the Resource' do
|
|
210
|
+
before :all do
|
|
211
|
+
@car.__send__("#{@name}=", @model.new)
|
|
212
|
+
@expected = @model.new
|
|
213
|
+
|
|
214
|
+
@return = @car.__send__("#{@name}=", @expected)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'returns the expected Resource' do
|
|
218
|
+
expect(@return).to equal(@expected)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it 'sets the Resource' do
|
|
222
|
+
expect(@car.__send__(@name)).to equal(@expected)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
relationship = Car.relationships[@name]
|
|
226
|
+
many_to_one = relationship.is_a?(DataMapper::Associations::ManyToOne::Relationship)
|
|
227
|
+
it 'relates associated Resource' do
|
|
228
|
+
one_to_one_through = relationship.is_a?(DataMapper::Associations::OneToOne::Relationship) && relationship.respond_to?(:through)
|
|
229
|
+
|
|
230
|
+
pending 'creates back-reference' if many_to_one || one_to_one_through
|
|
231
|
+
expect(@expected.car).to eq @car
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it 'persists the Resource' do
|
|
235
|
+
expect(@car.save).to be(true)
|
|
236
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to eq @expected
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it 'persists the associated Resource' do
|
|
240
|
+
expect(@car.save).to be(true)
|
|
241
|
+
expect(@expected).to be_saved
|
|
242
|
+
expect(@expected.model.get!(*@expected.key).car).to eq @car
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
shared_examples 'it creates a many accessor' do
|
|
249
|
+
describe 'accessor' do
|
|
250
|
+
describe 'when there is no child resource and the source is saved' do
|
|
251
|
+
before :all do
|
|
252
|
+
expect(@car.save).to be(true)
|
|
253
|
+
@return = @car.__send__(@name)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it 'returns a Collection' do
|
|
257
|
+
expect(@return).to be_kind_of(DataMapper::Collection)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'returns an empty Collection' do
|
|
261
|
+
expect(@return).to be_empty
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
describe 'when there is no child resource and the source is not saved' do
|
|
266
|
+
before :all do
|
|
267
|
+
@return = @car.__send__(@name)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'returns a Collection' do
|
|
271
|
+
expect(@return).to be_kind_of(DataMapper::Collection)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it 'returns an empty Collection' do
|
|
275
|
+
expect(@return).to be_empty
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
describe 'when there is a child resource' do
|
|
280
|
+
before :all do
|
|
281
|
+
@return = nil
|
|
282
|
+
|
|
283
|
+
@expected = @model.new
|
|
284
|
+
@car.__send__("#{@name}=", [@expected])
|
|
285
|
+
|
|
286
|
+
@return = @car.__send__(@name)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it 'returns a Collection' do
|
|
290
|
+
expect(@return).to be_kind_of(DataMapper::Collection)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
it 'returns expected Resources' do
|
|
294
|
+
expect(@return).to eq [@expected]
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
describe 'when the target model is scoped' do
|
|
299
|
+
before :all do
|
|
300
|
+
2.times { @car.__send__(@name).new }
|
|
301
|
+
@car.save
|
|
302
|
+
|
|
303
|
+
@expected = @car.__send__(@name).first
|
|
304
|
+
expect(@expected).not_to be_nil
|
|
305
|
+
|
|
306
|
+
# set the model scope to only return the first record
|
|
307
|
+
@model.default_scope.update(
|
|
308
|
+
@model.key(@repository.name).zip(@expected.key).to_h
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
@return = @car.model.get!(*@car.key).__send__(@name)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it 'returns a Collection' do
|
|
315
|
+
expect(@return).to be_kind_of(DataMapper::Collection)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it 'returns expected Resources' do
|
|
319
|
+
expect(@return).to eq [@expected]
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
shared_examples 'it creates a many mutator' do
|
|
326
|
+
describe 'mutator' do
|
|
327
|
+
describe 'when setting an Array of Resources' do
|
|
328
|
+
before :all do
|
|
329
|
+
@expected = [@model.new]
|
|
330
|
+
|
|
331
|
+
@return = @car.__send__("#{@name}=", @expected)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it 'returns the expected Collection' do
|
|
335
|
+
expect(@return).to eq @expected
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it 'sets the Collection' do
|
|
339
|
+
expect(@car.__send__(@name)).to eq @expected
|
|
340
|
+
@car.__send__(@name).zip(@expected) { |value, expected| expect(value).to equal(expected) }
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it 'relates the associated Collection' do
|
|
344
|
+
pending if Car.relationships[@name].is_a?(DataMapper::Associations::ManyToMany::Relationship)
|
|
345
|
+
@expected.each { |resource| expect(resource.car).to eq @car }
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it 'persists the Collection' do
|
|
349
|
+
expect(@car.save).to be(true)
|
|
350
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to eq @expected
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it 'persists the associated Resource' do
|
|
354
|
+
expect(@car.save).to be(true)
|
|
355
|
+
@expected.each do |resource|
|
|
356
|
+
expect(resource).to be_saved
|
|
357
|
+
expect(resource.model.get!(*resource.key).car).to eq @car
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
describe 'when setting an Array of Hashes' do
|
|
363
|
+
before :all do
|
|
364
|
+
attributes = {id: 11}
|
|
365
|
+
@hashes = [attributes]
|
|
366
|
+
@expected = [@model.new(attributes)]
|
|
367
|
+
|
|
368
|
+
@return = @car.__send__("#{@name}=", @hashes)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
it 'returns the expected Collection' do
|
|
372
|
+
expect(@return).to eq @expected
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it 'sets the Collection' do
|
|
376
|
+
expect(@car.__send__(@name)).to eq @return
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it 'relates the associated Collection' do
|
|
380
|
+
pending if Car.relationships[@name].is_a?(DataMapper::Associations::ManyToMany::Relationship)
|
|
381
|
+
@return.each { |resource| expect(resource.car).to eq @car }
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
it 'persists the Collection' do
|
|
385
|
+
expect(@car.save).to be(true)
|
|
386
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to eq @return
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
it 'persists the associated Resource' do
|
|
390
|
+
expect(@car.save).to be(true)
|
|
391
|
+
@return&.each do |resource|
|
|
392
|
+
expect(resource).to be_saved
|
|
393
|
+
expect(resource.model.get!(*resource.key).car).to eq @car
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
describe 'when setting an empty collection' do
|
|
399
|
+
before :all do
|
|
400
|
+
@car.__send__("#{@name}=", [@model.new])
|
|
401
|
+
|
|
402
|
+
@return = @car.__send__("#{@name}=", [])
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it 'returns a Collection' do
|
|
406
|
+
expect(@return).to be_kind_of(DataMapper::Collection)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
it 'sets an empty Collection' do
|
|
410
|
+
expect(@car.__send__(@name)).to be_empty
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
it 'persists as an empty Collection' do
|
|
414
|
+
expect(@car.save).to be(true)
|
|
415
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to be_empty
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
describe 'when changing an associated collection' do
|
|
420
|
+
before :all do
|
|
421
|
+
@car.__send__("#{@name}=", [@model.new])
|
|
422
|
+
|
|
423
|
+
@expected = [@model.new]
|
|
424
|
+
|
|
425
|
+
@return = @car.__send__("#{@name}=", @expected)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it 'returns the expected Resource' do
|
|
429
|
+
expect(@return).to eq @expected
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it 'sets the Resource' do
|
|
433
|
+
expect(@car.__send__(@name)).to eq @expected
|
|
434
|
+
@car.__send__(@name).zip(@expected) { |value, expected| expect(value).to equal(expected) }
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
it 'relates associated Resource' do
|
|
438
|
+
pending if Car.relationships[@name].is_a?(DataMapper::Associations::ManyToMany::Relationship)
|
|
439
|
+
@expected.each { |resource| expect(resource.car).to eq @car }
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it 'persists the Resource' do
|
|
443
|
+
expect(@car.save).to be(true)
|
|
444
|
+
expect(@car.model.get!(*@car.key).__send__(@name)).to eq @expected
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it 'persists the associated Resource' do
|
|
448
|
+
expect(@car.save).to be(true)
|
|
449
|
+
@expected.each do |resource|
|
|
450
|
+
expect(resource).to be_saved
|
|
451
|
+
expect(resource.model.get!(*resource.key).car).to eq @car
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
describe DataMapper::Associations do
|
|
459
|
+
before :all do
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
def n
|
|
463
|
+
1.0/0
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
it { expect(Engine).to respond_to(:belongs_to) }
|
|
467
|
+
|
|
468
|
+
describe '#belongs_to' do
|
|
469
|
+
before :all do
|
|
470
|
+
@model = Engine
|
|
471
|
+
@name = :engine
|
|
472
|
+
|
|
473
|
+
Car.belongs_to(@name, required: false)
|
|
474
|
+
Engine.has(1, :car)
|
|
475
|
+
DataMapper.finalize
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
supported_by :all do
|
|
479
|
+
before :all do
|
|
480
|
+
@car = Car.new
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
it { expect(@car).to respond_to(@name) }
|
|
484
|
+
|
|
485
|
+
it_behaves_like 'it creates a one accessor'
|
|
486
|
+
|
|
487
|
+
it { expect(@car).to respond_to("#{@name}=") }
|
|
488
|
+
|
|
489
|
+
it_behaves_like 'it creates a one mutator'
|
|
490
|
+
|
|
491
|
+
describe 'with a :key option' do
|
|
492
|
+
before :all do
|
|
493
|
+
@relationship = Car.belongs_to("#{@name}_with_key".to_sym, @model, required: false, key: true)
|
|
494
|
+
DataMapper.finalize
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
it 'creates a foreign key that is part of the key' do
|
|
498
|
+
@relationship.child_key.each do |property|
|
|
499
|
+
expect(property).to be_key
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
describe 'with a :unique option' do
|
|
505
|
+
let(:unique) { %i(one two three) }
|
|
506
|
+
|
|
507
|
+
before :all do
|
|
508
|
+
@relationship = Car.belongs_to("#{@name}_with_unique".to_sym, @model, unique: unique)
|
|
509
|
+
DataMapper.finalize
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it 'creates a foreign key that is unique' do
|
|
513
|
+
@relationship.child_key.each do |property|
|
|
514
|
+
expect(property).to be_unique
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
it 'creates a foreign key that has a unique index' do
|
|
519
|
+
@relationship.child_key.each do |property|
|
|
520
|
+
expect(property.unique_index).to equal(unique)
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# TODO: refactor these specs into above structure once they pass
|
|
527
|
+
describe 'pending query specs' do
|
|
528
|
+
before :all do
|
|
529
|
+
Car.has(1, :engine)
|
|
530
|
+
Engine.belongs_to(:car)
|
|
531
|
+
DataMapper.finalize
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
supported_by :all do
|
|
535
|
+
describe 'querying for a parent resource when only the foreign key is set' do
|
|
536
|
+
before :all do
|
|
537
|
+
# create a car that would be returned if the query is not
|
|
538
|
+
# scoped properly to retrieve @car
|
|
539
|
+
Car.create
|
|
540
|
+
|
|
541
|
+
@car = Car.create
|
|
542
|
+
engine = Engine.new(car_id: @car.id)
|
|
543
|
+
|
|
544
|
+
@return = engine.car
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
it 'returns a Resource' do
|
|
548
|
+
expect(@return).to be_kind_of(DataMapper::Resource)
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
it 'returns expected Resource' do
|
|
552
|
+
expect(@return).to eql(@car)
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
describe 'querying for a parent resource' do
|
|
557
|
+
before :all do
|
|
558
|
+
@car = Car.create
|
|
559
|
+
@engine = Engine.create(car: @car)
|
|
560
|
+
@resource = @engine.car(id: @car.id)
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
it 'returns a Resource' do
|
|
564
|
+
expect(@resource).to be_kind_of(DataMapper::Resource)
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it 'returns expected Resource' do
|
|
568
|
+
expect(@resource).to eql(@car)
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
describe 'querying for a parent resource that does not exist' do
|
|
573
|
+
before :all do
|
|
574
|
+
@car = Car.create
|
|
575
|
+
@engine = Engine.create(car: @car)
|
|
576
|
+
@resource = @engine.car(:id.not => @car.id)
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
it 'returns nil' do
|
|
580
|
+
expect(@resource).to be_nil
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
describe 'changing the parent resource' do
|
|
585
|
+
before :all do
|
|
586
|
+
@car = Car.create
|
|
587
|
+
@engine = Engine.new
|
|
588
|
+
@engine.car = @car
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
it 'sets the associated foreign key' do
|
|
592
|
+
expect(@engine.car_id).to eq @car.id
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
it 'adds the engine object to the car' do
|
|
596
|
+
pending 'Changing a belongs_to parent adds the object to the correct association'
|
|
597
|
+
|
|
598
|
+
expect(@car.engines).to include(@engine)
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
describe 'changing the parent foreign key' do
|
|
603
|
+
before :all do
|
|
604
|
+
@car = Car.create
|
|
605
|
+
|
|
606
|
+
@engine = Engine.new(car_id: @car.id)
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
it 'sets the associated resource' do
|
|
610
|
+
expect(@engine.car).to eql(@car)
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
describe 'changing an existing resource through the relation' do
|
|
615
|
+
before :all do
|
|
616
|
+
@car1 = Car.create
|
|
617
|
+
@car2 = Car.create
|
|
618
|
+
@engine = Engine.create(car: @car1)
|
|
619
|
+
@engine.car = @car2
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
it 'also changes the foreign key' do
|
|
623
|
+
expect(@engine.car_id).to eq @car2.id
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
it 'adds the engine to the car' do
|
|
627
|
+
pending 'Changing a belongs_to parent adds the object to the correct association'
|
|
628
|
+
expect(@car2.engines).to include(@engine)
|
|
629
|
+
end
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
describe 'changing an existing resource through the relation' do
|
|
633
|
+
before :all do
|
|
634
|
+
@car1 = Car.create
|
|
635
|
+
@car2 = Car.create
|
|
636
|
+
@engine = Engine.create(car: @car1)
|
|
637
|
+
@engine.car_id = @car2.id
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
it 'also changes the foreign key' do
|
|
641
|
+
expect(@engine.car).to eql(@car2)
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
it 'adds the engine to the car' do
|
|
645
|
+
pending 'a change to the foreign key also changes the related object'
|
|
646
|
+
expect(@car2.engines).to include(@engine)
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
describe 'with a model' do
|
|
653
|
+
before :all do
|
|
654
|
+
Engine.belongs_to(:vehicle, Car)
|
|
655
|
+
DataMapper.finalize
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
it 'sets the relationship target model' do
|
|
659
|
+
expect(Engine.relationships[:vehicle].target_model).to eq Car
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
describe 'with a :model option' do
|
|
664
|
+
before :all do
|
|
665
|
+
Engine.belongs_to(:vehicle, model: Car)
|
|
666
|
+
DataMapper.finalize
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
it 'sets the relationship target model' do
|
|
670
|
+
expect(Engine.relationships[:vehicle].target_model).to eq Car
|
|
671
|
+
end
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
describe 'with a single element as :child_key option' do
|
|
675
|
+
before :all do
|
|
676
|
+
Engine.belongs_to(:vehicle, model: Car, child_key: :bike_id)
|
|
677
|
+
DataMapper.finalize
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
it 'sets the relationship child key' do
|
|
681
|
+
expect(Engine.relationships[:vehicle].child_key.map(&:name)).to eq [:bike_id]
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
describe 'with an array as :child_key option' do
|
|
686
|
+
before :all do
|
|
687
|
+
Engine.belongs_to(:vehicle, model: Car, child_key: [:bike_id])
|
|
688
|
+
DataMapper.finalize
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
it 'sets the relationship child key' do
|
|
692
|
+
expect(Engine.relationships[:vehicle].child_key.map(&:name)).to eq [:bike_id]
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
describe 'with a single element as :parent_key option' do
|
|
697
|
+
before :all do
|
|
698
|
+
Engine.belongs_to(:vehicle, model: Car, parent_key: :name)
|
|
699
|
+
DataMapper.finalize
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
it 'sets the relationship parent key' do
|
|
703
|
+
expect(Engine.relationships[:vehicle].parent_key.map(&:name)).to eq [:name]
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
describe 'with an array as :parent_key option' do
|
|
708
|
+
before :all do
|
|
709
|
+
Engine.belongs_to(:vehicle, model: Car, parent_key: [:name])
|
|
710
|
+
DataMapper.finalize
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
it 'sets the relationship parent key' do
|
|
714
|
+
expect(Engine.relationships[:vehicle].parent_key.map(&:name)).to eq [:name]
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
it { expect(Car).to respond_to(:has) }
|
|
720
|
+
|
|
721
|
+
describe '#has' do
|
|
722
|
+
describe '1' do
|
|
723
|
+
before :all do
|
|
724
|
+
@model = Engine
|
|
725
|
+
@name = :engine
|
|
726
|
+
|
|
727
|
+
Car.has(1, @name)
|
|
728
|
+
Engine.belongs_to(:car)
|
|
729
|
+
DataMapper.finalize
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
supported_by :all do
|
|
733
|
+
before :all do
|
|
734
|
+
@car = Car.new
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
it { expect(@car).to respond_to(@name) }
|
|
738
|
+
|
|
739
|
+
it_behaves_like 'it creates a one accessor'
|
|
740
|
+
|
|
741
|
+
it { expect(@car).to respond_to("#{@name}=") }
|
|
742
|
+
|
|
743
|
+
it_behaves_like 'it creates a one mutator'
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
describe '1 through' do
|
|
748
|
+
before :all do
|
|
749
|
+
@model = Engine
|
|
750
|
+
@name = :engine
|
|
751
|
+
|
|
752
|
+
Car.has(1, @name, through: DataMapper::Resource)
|
|
753
|
+
Engine.has(1, :car, through: DataMapper::Resource)
|
|
754
|
+
DataMapper.finalize
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
supported_by :all do
|
|
758
|
+
before :all do
|
|
759
|
+
@no_join = (defined?(DataMapper::Adapters::InMemoryAdapter) && @adapter.is_a?(DataMapper::Adapters::InMemoryAdapter)) ||
|
|
760
|
+
(defined?(DataMapper::Adapters::YamlAdapter) && @adapter.is_a?(DataMapper::Adapters::YamlAdapter))
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
before :all do
|
|
764
|
+
@car = Car.new
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
before do
|
|
768
|
+
pending if @no_join
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
it { expect(@car).to respond_to(@name) }
|
|
772
|
+
|
|
773
|
+
it_behaves_like 'it creates a one accessor'
|
|
774
|
+
|
|
775
|
+
it { expect(@car).to respond_to("#{@name}=") }
|
|
776
|
+
|
|
777
|
+
it_behaves_like 'it creates a one mutator'
|
|
778
|
+
end
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
describe 'n..n' do
|
|
782
|
+
before :all do
|
|
783
|
+
@model = Door
|
|
784
|
+
@name = :doors
|
|
785
|
+
|
|
786
|
+
Car.has(1..4, @name)
|
|
787
|
+
Door.belongs_to(:car, required: false)
|
|
788
|
+
DataMapper.finalize
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
supported_by :all do
|
|
792
|
+
before :all do
|
|
793
|
+
@car = Car.new
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
it { expect(@car).to respond_to(@name) }
|
|
797
|
+
|
|
798
|
+
it_behaves_like 'it creates a many accessor'
|
|
799
|
+
|
|
800
|
+
it { expect(@car).to respond_to("#{@name}=") }
|
|
801
|
+
|
|
802
|
+
it_behaves_like 'it creates a many mutator'
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
describe 'n..n through' do
|
|
807
|
+
before :all do
|
|
808
|
+
@model = Window
|
|
809
|
+
@name = :windows
|
|
810
|
+
|
|
811
|
+
Window.has(1, :car, through: DataMapper::Resource)
|
|
812
|
+
Car.has(1..4, :windows, through: DataMapper::Resource)
|
|
813
|
+
DataMapper.finalize
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
supported_by :all do
|
|
817
|
+
before :all do
|
|
818
|
+
@no_join = (defined?(DataMapper::Adapters::InMemoryAdapter) && @adapter.is_a?(DataMapper::Adapters::InMemoryAdapter)) ||
|
|
819
|
+
(defined?(DataMapper::Adapters::YamlAdapter) && @adapter.is_a?(DataMapper::Adapters::YamlAdapter))
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
before :all do
|
|
823
|
+
@car = Car.new
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
before do
|
|
827
|
+
pending if @no_join
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
it { expect(@car).to respond_to(@name) }
|
|
831
|
+
|
|
832
|
+
it_behaves_like 'it creates a many accessor'
|
|
833
|
+
|
|
834
|
+
it { expect(@car).to respond_to("#{@name}=") }
|
|
835
|
+
|
|
836
|
+
it_behaves_like 'it creates a many mutator'
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
describe 'when the 3rd argument is a Model' do
|
|
841
|
+
before :all do
|
|
842
|
+
Car.has(1, :engine, Engine)
|
|
843
|
+
DataMapper.finalize
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
it 'sets the relationship target model' do
|
|
847
|
+
expect(Car.relationships[:engine].target_model).to eq Engine
|
|
848
|
+
end
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
describe 'when the 3rd argument is a String' do
|
|
852
|
+
before :all do
|
|
853
|
+
Car.has(1, :engine, 'Engine')
|
|
854
|
+
DataMapper.finalize
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
it 'sets the relationship target model' do
|
|
858
|
+
expect(Car.relationships[:engine].target_model).to eq Engine
|
|
859
|
+
end
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
it 'raises an exception if the cardinality is not understood' do
|
|
863
|
+
expect { Car.has(n..n, :doors) }.to raise_error(ArgumentError)
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
it 'raises an exception if the minimum constraint is larger than the maximum' do
|
|
867
|
+
expect { Car.has(2..1, :doors) }.to raise_error(ArgumentError)
|
|
868
|
+
end
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
describe 'property prefix inference' do
|
|
872
|
+
describe 'when a relationship has an inverse' do
|
|
873
|
+
before :all do
|
|
874
|
+
@engine_relationship = Car.has(1, :engine, inverse: Engine.belongs_to(:sports_car, Car))
|
|
875
|
+
DataMapper.finalize
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
supported_by :all do
|
|
879
|
+
it 'has a child key prefix the same as the inverse relationship' do
|
|
880
|
+
expect(@engine_relationship.child_key.map(&:name)).to eq [:sports_car_id]
|
|
881
|
+
end
|
|
882
|
+
end
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
describe 'when a relationship does not have an inverse' do
|
|
886
|
+
before :all do
|
|
887
|
+
@engine_relationship = Car.has(1, :engine)
|
|
888
|
+
DataMapper.finalize
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
supported_by :all do
|
|
892
|
+
it 'has a child key prefix inferred from the source model name' do
|
|
893
|
+
expect(@engine_relationship.child_key.map(&:name)).to eq [:car_id]
|
|
894
|
+
end
|
|
895
|
+
end
|
|
896
|
+
end
|
|
897
|
+
|
|
898
|
+
describe 'when a relationship is inherited' do
|
|
899
|
+
describe 'has an inverse' do
|
|
900
|
+
before :all do
|
|
901
|
+
Car.property(:type, DataMapper::Property::Discriminator)
|
|
902
|
+
|
|
903
|
+
class ::ElectricCar < Car; end
|
|
904
|
+
|
|
905
|
+
Car.has(1, :engine, inverse: Engine.belongs_to(:sports_car, Car))
|
|
906
|
+
DataMapper.finalize
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
supported_by :all do
|
|
910
|
+
before :all do
|
|
911
|
+
@engine_relationship = ElectricCar.relationships(@repository.name)[:engine]
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
it 'has a source model equal to the ancestor' do
|
|
915
|
+
expect(@engine_relationship.source_model).to equal(Car)
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
it 'has a child key prefix the same as the inverse relationship' do
|
|
919
|
+
expect(@engine_relationship.child_key.map(&:name)).to eq [:sports_car_id]
|
|
920
|
+
end
|
|
921
|
+
end
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
describe 'does not have an inverse' do
|
|
925
|
+
before :all do
|
|
926
|
+
Car.property(:type, DataMapper::Property::Discriminator)
|
|
927
|
+
|
|
928
|
+
class ::ElectricCar < Car; end
|
|
929
|
+
|
|
930
|
+
Car.has(1, :engine)
|
|
931
|
+
DataMapper.finalize
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
supported_by :all do
|
|
935
|
+
before :all do
|
|
936
|
+
@engine_relationship = ElectricCar.relationships(@repository.name)[:engine]
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
it 'has a source model equal to the ancestor' do
|
|
940
|
+
expect(@engine_relationship.source_model).to equal(Car)
|
|
941
|
+
end
|
|
942
|
+
|
|
943
|
+
it 'has a child key prefix inferred from the source model name' do
|
|
944
|
+
expect(@engine_relationship.child_key.map(&:name)).to eq [:car_id]
|
|
945
|
+
end
|
|
946
|
+
end
|
|
947
|
+
end
|
|
948
|
+
end
|
|
949
|
+
|
|
950
|
+
describe "when a subclass defines it's own relationship" do
|
|
951
|
+
describe 'has an inverse' do
|
|
952
|
+
before :all do
|
|
953
|
+
Car.property(:type, DataMapper::Property::Discriminator)
|
|
954
|
+
|
|
955
|
+
class ::ElectricCar < Car; end
|
|
956
|
+
|
|
957
|
+
ElectricCar.has(1, :engine, inverse: Engine.belongs_to(:sports_car, Car))
|
|
958
|
+
DataMapper.finalize
|
|
959
|
+
end
|
|
960
|
+
|
|
961
|
+
supported_by :all do
|
|
962
|
+
before :all do
|
|
963
|
+
@engine_relationship = ElectricCar.relationships(@repository.name)[:engine]
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
it 'has a source model equal to the descendant' do
|
|
967
|
+
expect(@engine_relationship.source_model).to equal(ElectricCar)
|
|
968
|
+
end
|
|
969
|
+
|
|
970
|
+
it 'has a child key prefix the same as the inverse relationship' do
|
|
971
|
+
expect(@engine_relationship.child_key.map(&:name)).to eq [:sports_car_id]
|
|
972
|
+
end
|
|
973
|
+
end
|
|
974
|
+
end
|
|
975
|
+
|
|
976
|
+
describe 'does not have an inverse' do
|
|
977
|
+
before :all do
|
|
978
|
+
Car.property(:type, DataMapper::Property::Discriminator)
|
|
979
|
+
|
|
980
|
+
class ::ElectricCar < Car; end
|
|
981
|
+
|
|
982
|
+
ElectricCar.has(1, :engine)
|
|
983
|
+
DataMapper.finalize
|
|
984
|
+
end
|
|
985
|
+
|
|
986
|
+
supported_by :all do
|
|
987
|
+
before :all do
|
|
988
|
+
@engine_relationship = ElectricCar.relationships(@repository.name)[:engine]
|
|
989
|
+
end
|
|
990
|
+
|
|
991
|
+
it 'has a source model equal to the descendant' do
|
|
992
|
+
expect(@engine_relationship.source_model).to equal(ElectricCar)
|
|
993
|
+
end
|
|
994
|
+
|
|
995
|
+
it 'has a child key prefix inferred from the source model name' do
|
|
996
|
+
expect(@engine_relationship.child_key.map(&:name)).to eq [:electric_car_id]
|
|
997
|
+
end
|
|
998
|
+
end
|
|
999
|
+
end
|
|
1000
|
+
end
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
describe 'child is also a parent' do
|
|
1004
|
+
before :all do
|
|
1005
|
+
class ::Employee
|
|
1006
|
+
include DataMapper::Resource
|
|
1007
|
+
|
|
1008
|
+
property :id, Serial
|
|
1009
|
+
property :name, String
|
|
1010
|
+
|
|
1011
|
+
belongs_to :company
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
class ::Company
|
|
1015
|
+
include DataMapper::Resource
|
|
1016
|
+
|
|
1017
|
+
property :id, Serial
|
|
1018
|
+
property :name, String
|
|
1019
|
+
|
|
1020
|
+
belongs_to :owner, Employee, required: false
|
|
1021
|
+
has n, :employees
|
|
1022
|
+
end
|
|
1023
|
+
DataMapper.finalize
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
supported_by :all do
|
|
1027
|
+
before :all do
|
|
1028
|
+
@company = Company.create(name: 'ACME Inc.')
|
|
1029
|
+
@employee = @company.employees.create(name: 'Wil E. Coyote')
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
it 'saves the child as a parent' do
|
|
1033
|
+
expect {
|
|
1034
|
+
@company.owner = @employee
|
|
1035
|
+
expect(@company.save).to be(true)
|
|
1036
|
+
}.not_to raise_error
|
|
1037
|
+
end
|
|
1038
|
+
end
|
|
1039
|
+
end
|
|
1040
|
+
end
|