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,1221 @@
|
|
|
1
|
+
shared_examples 'A public Resource' do
|
|
2
|
+
before :all do
|
|
3
|
+
@no_join = defined?(DataMapper::Adapters::InMemoryAdapter) && @adapter.kind_of?(DataMapper::Adapters::InMemoryAdapter) ||
|
|
4
|
+
defined?(DataMapper::Adapters::YamlAdapter) && @adapter.kind_of?(DataMapper::Adapters::YamlAdapter)
|
|
5
|
+
|
|
6
|
+
relationship = @user_model.relationships[:referrer]
|
|
7
|
+
@one_to_one_through = relationship.kind_of?(DataMapper::Associations::OneToOne::Relationship) && relationship.respond_to?(:through)
|
|
8
|
+
|
|
9
|
+
@skip = @no_join && @one_to_one_through
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
before :all do
|
|
13
|
+
unless @skip
|
|
14
|
+
%w[ @user_model @user @comment_model ].each do |ivar|
|
|
15
|
+
raise "+#{ivar}+ should be defined in before block" unless instance_variable_get(ivar)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before do
|
|
21
|
+
pending if @skip
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
%i(== ===).each do |method|
|
|
25
|
+
it { expect(@user).to respond_to(method) }
|
|
26
|
+
|
|
27
|
+
describe "##{method}" do
|
|
28
|
+
describe 'when comparing to the same resource' do
|
|
29
|
+
before :all do
|
|
30
|
+
@other = @user
|
|
31
|
+
@return = @user.__send__(method, @other)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'returns true' do
|
|
35
|
+
expect(@return).to be(true)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'when comparing to an resource that does not respond to resource methods' do
|
|
40
|
+
before :all do
|
|
41
|
+
@other = Object.new
|
|
42
|
+
@return = @user.__send__(method, @other)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns false' do
|
|
46
|
+
expect(@return).to be(false)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe 'when comparing to a resource with the same properties, but the model is a subclass' do
|
|
51
|
+
before :all do
|
|
52
|
+
rescue_if @skip do
|
|
53
|
+
@other = @author_model.new(@user.attributes)
|
|
54
|
+
@return = @user.__send__(method, @other)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'returns true' do
|
|
59
|
+
expect(@return).to be(true)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe 'when comparing to a resource with the same repository, key and neither self or the other resource is dirty' do
|
|
64
|
+
before :all do
|
|
65
|
+
rescue_if @skip do
|
|
66
|
+
@other = @user_model.get(*@user.key)
|
|
67
|
+
@return = @user.__send__(method, @other)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'returns true' do
|
|
72
|
+
expect(@return).to be(true)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe 'when comparing to a resource with the same repository, key but either self or the other resource is dirty' do
|
|
77
|
+
before :all do
|
|
78
|
+
rescue_if @skip do
|
|
79
|
+
@user.age = 20
|
|
80
|
+
@other = @user_model.get(*@user.key)
|
|
81
|
+
@return = @user.__send__(method, @other)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'returns false' do
|
|
86
|
+
expect(@return).to be(false)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe 'when comparing to a resource with the same properties' do
|
|
91
|
+
before :all do
|
|
92
|
+
rescue_if @skip do
|
|
93
|
+
@other = @user_model.new(@user.attributes)
|
|
94
|
+
@return = @user.__send__(method, @other)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'returns true' do
|
|
99
|
+
expect(@return).to be(true)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
with_alternate_adapter do
|
|
104
|
+
before :all do
|
|
105
|
+
if @user_model.respond_to?(:auto_migrate!)
|
|
106
|
+
# force the user model to be available in the alternate repository
|
|
107
|
+
@user_model.auto_migrate!(@adapter.name)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe 'when comparing to a resource with a different repository, but the same properties' do
|
|
112
|
+
before :all do
|
|
113
|
+
rescue_if @skip do
|
|
114
|
+
@other = @repository.scope { @user_model.create(@user.attributes) }
|
|
115
|
+
@return = @user.__send__(method, @other)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'returns false' do
|
|
120
|
+
expect(@return).to be(false)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it { expect(@user).to respond_to(:<=>) }
|
|
128
|
+
|
|
129
|
+
describe '#<=>' do
|
|
130
|
+
describe 'when the default order properties are equal with another resource' do
|
|
131
|
+
before :all do
|
|
132
|
+
rescue_if @skip && RUBY_VERSION < '1.9.2' do
|
|
133
|
+
@other = @user_model.new(:name => 'dbussink')
|
|
134
|
+
@return = @user <=> @other
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'returns 0' do
|
|
139
|
+
expect(@return).to eq 0
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe 'when the default order property values are sorted before another resource' do
|
|
144
|
+
before :all do
|
|
145
|
+
rescue_if @skip && RUBY_VERSION < '1.9.2' do
|
|
146
|
+
@other = @user_model.new(:name => 'c')
|
|
147
|
+
@return = @user <=> @other
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'returns 1' do
|
|
152
|
+
expect(@return).to eq 1
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
describe 'when the default order property values are sorted after another resource' do
|
|
157
|
+
before :all do
|
|
158
|
+
rescue_if @skip && RUBY_VERSION < '1.9.2' do
|
|
159
|
+
@other = @user_model.new(:name => 'e')
|
|
160
|
+
@return = @user <=> @other
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'returns -1' do
|
|
165
|
+
expect(@return).to eq -1
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe 'when comparing an unrelated type of Object' do
|
|
170
|
+
it 'raises an exception' do
|
|
171
|
+
expect {
|
|
172
|
+
@user <=> @comment_model.new
|
|
173
|
+
}.to raise_error(ArgumentError, "Cannot compare a #{@comment_model} instance with a #{@user_model} instance")
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it { expect(@user).to respond_to(:attribute_get) }
|
|
179
|
+
|
|
180
|
+
describe '#attribute_get' do
|
|
181
|
+
it { expect(@user.attribute_get(:name)).to eq 'dbussink' }
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it { expect(@user).to respond_to(:attribute_set) }
|
|
185
|
+
|
|
186
|
+
describe '#attribute_set' do
|
|
187
|
+
before { @user.attribute_set(:name, 'dkubb') }
|
|
188
|
+
|
|
189
|
+
it { expect(@user.name).to eq 'dkubb' }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it { expect(@user).to respond_to(:attributes) }
|
|
193
|
+
|
|
194
|
+
describe '#attributes' do
|
|
195
|
+
describe 'with a new resource' do
|
|
196
|
+
before :all do
|
|
197
|
+
rescue_if @skip do
|
|
198
|
+
@user = @user.model.new
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'returns the expected values' do
|
|
203
|
+
expect(@user.attributes).to eq({})
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
describe 'with a new resource with a property set' do
|
|
208
|
+
before :all do
|
|
209
|
+
rescue_if @skip do
|
|
210
|
+
@user = @user.model.new
|
|
211
|
+
@user.name = 'dbussink'
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'returns the expected values' do
|
|
216
|
+
expect(@user.attributes).to eq({name: 'dbussink'})
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
describe 'with a saved resource' do
|
|
221
|
+
it 'returns the expected values' do
|
|
222
|
+
expect(DataMapper::Ext::Hash.only(@user.attributes, :name, :description, :age)).to eq({name: 'dbussink', description: 'Test', age: 25})
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it { expect(@user).to respond_to(:attributes=) }
|
|
228
|
+
|
|
229
|
+
describe '#attributes=' do
|
|
230
|
+
describe 'when a public mutator is specified' do
|
|
231
|
+
before :all do
|
|
232
|
+
rescue_if @skip do
|
|
233
|
+
@user.attributes = { :name => 'dkubb', @user.class.properties[:age] => '42' }
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'sets the value' do
|
|
238
|
+
expect(@user.name).to eql('dkubb')
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it 'typecasts and sets the value' do
|
|
242
|
+
expect(@use.age).to eql(42)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe 'when a non-public mutator is specified' do
|
|
247
|
+
it 'raises an exception' do
|
|
248
|
+
expect {
|
|
249
|
+
@user.attributes = {admin: true}
|
|
250
|
+
}.to raise_error(ArgumentError, "The attribute \'admin\' is not accessible in #{@user_model}")
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
%i(destroy destroy!).each do |method|
|
|
256
|
+
it { expect(@user).to respond_to(:destroy) }
|
|
257
|
+
|
|
258
|
+
describe "##{method}" do
|
|
259
|
+
describe 'on a single resource' do
|
|
260
|
+
before :all do
|
|
261
|
+
@resource = @user_model.create(:name => 'hacker', :age => 20, :comment => @comment)
|
|
262
|
+
|
|
263
|
+
@return = @resource.__send__(method)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it 'successfully removes a resource' do
|
|
267
|
+
expect(@return).to be(true)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'marks the destroyed resource as readonly' do
|
|
271
|
+
expect(@resource).to be_readonly
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it "returns true when calling #{method} on a destroyed resource" do
|
|
275
|
+
expect(@resource.__send__(method)).to be(true)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it 'removes resource from persistent storage' do
|
|
279
|
+
expect(@user_model.get(*@resource.key)).to be_nil
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
describe 'with has relationship resources' do
|
|
284
|
+
it 'raises an exception'
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it { expect(@user).to respond_to(:dirty?) }
|
|
290
|
+
|
|
291
|
+
describe '#dirty?' do
|
|
292
|
+
describe 'on a record, with dirty attributes' do
|
|
293
|
+
before { @user.age = 100 }
|
|
294
|
+
|
|
295
|
+
it { expect(@user).to be_dirty }
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
describe 'on a record, with no dirty attributes, and dirty parents' do
|
|
299
|
+
before :all do
|
|
300
|
+
rescue_if @skip do
|
|
301
|
+
expect(@user).not_to be_dirty
|
|
302
|
+
|
|
303
|
+
parent = @user.parent = @user_model.new(:name => 'Parent')
|
|
304
|
+
expect(parent).to be_dirty
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it { expect(@user).to be_dirty }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
describe 'on a record, with no dirty attributes, and dirty children' do
|
|
312
|
+
before :all do
|
|
313
|
+
rescue_if @skip do
|
|
314
|
+
expect(@user).not_to be_dirty
|
|
315
|
+
|
|
316
|
+
child = @user.children.new(:name => 'Child')
|
|
317
|
+
expect(child).to be_dirty
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it { expect(@user).to be_dirty }
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
describe 'on a record, with no dirty attributes, and dirty siblings' do
|
|
325
|
+
before :all do
|
|
326
|
+
rescue_if @skip do
|
|
327
|
+
expect(@user).not_to be_dirty
|
|
328
|
+
|
|
329
|
+
parent = @user_model.create(:name => 'Parent', :comment => @comment)
|
|
330
|
+
expect(parent).not_to be_dirty
|
|
331
|
+
|
|
332
|
+
@user.update(:parent => parent)
|
|
333
|
+
expect(@user).not_to be_dirty
|
|
334
|
+
|
|
335
|
+
sibling = parent.children.new(:name => 'Sibling')
|
|
336
|
+
expect(sibling).to be_dirty
|
|
337
|
+
expect(parent).to be_dirty
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it { expect(@user).not_to be_dirty }
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
describe 'on a saved record, with no dirty attributes' do
|
|
345
|
+
it { expect(@user).not_to be_dirty }
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
describe 'on a new record, with no dirty attributes, no default attributes, and no identity field' do
|
|
349
|
+
before { @user = @user_model.new }
|
|
350
|
+
|
|
351
|
+
it { expect(@user).not_to be_dirty }
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
describe 'on a new record, with no dirty attributes, no default attributes, and an identity field' do
|
|
355
|
+
before { @comment = @comment_model.new }
|
|
356
|
+
|
|
357
|
+
it { expect(@comment).to be_dirty }
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
describe 'on a new record, with no dirty attributes, default attributes, and no identity field' do
|
|
361
|
+
before { @default = Default.new }
|
|
362
|
+
|
|
363
|
+
it { expect(@default).to be_dirty }
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
describe 'on a record with itself as a parent (circular dependency)' do
|
|
367
|
+
before :all do
|
|
368
|
+
rescue_if @skip do
|
|
369
|
+
@user.parent = @user
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
it 'does not raise an exception' do
|
|
374
|
+
expect {
|
|
375
|
+
expect(@user.dirty?).to be(true)
|
|
376
|
+
}.not_to raise_error(SystemStackError)
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
describe 'on a record with itself as a child (circular dependency)' do
|
|
381
|
+
before :all do
|
|
382
|
+
rescue_if @skip do
|
|
383
|
+
@user.children = [ @user ]
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
it 'does not raise an exception' do
|
|
388
|
+
except {
|
|
389
|
+
expect(@user.dirty?).to be(true)
|
|
390
|
+
}.not_to raise_error(SystemStackError)
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
describe 'on a record with a parent as a child (circular dependency)' do
|
|
395
|
+
before :all do
|
|
396
|
+
rescue_if @skip do
|
|
397
|
+
@user.children = [ @user.parent = @user_model.new(:name => 'Parent', :comment => @comment) ]
|
|
398
|
+
expect(@user.save).to be(true)
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it 'does not raise an exception' do
|
|
403
|
+
expect {
|
|
404
|
+
expect(@user.dirty?).to be(true)
|
|
405
|
+
}.not_to raise_error
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
it { expect(@user).to respond_to(:eql?) }
|
|
411
|
+
|
|
412
|
+
describe '#eql?' do
|
|
413
|
+
describe 'when comparing to the same resource' do
|
|
414
|
+
before :all do
|
|
415
|
+
@other = @user
|
|
416
|
+
@return = @user.eql?(@other)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it 'returns true' do
|
|
420
|
+
expect(@return).to be(true)
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
describe 'when comparing to an resource that does not respond to model' do
|
|
425
|
+
before :all do
|
|
426
|
+
@other = Object.new
|
|
427
|
+
@return = @user.eql?(@other)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
it 'returns false' do
|
|
431
|
+
expect(@return).to be(false)
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
describe 'when comparing to a resource with the same properties, but the model is a subclass' do
|
|
436
|
+
before :all do
|
|
437
|
+
rescue_if @skip do
|
|
438
|
+
@other = @author_model.new(@user.attributes)
|
|
439
|
+
@return = @user.eql?(@other)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
it 'returns false' do
|
|
444
|
+
expect(@return).to be(false)
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
describe 'when comparing to a resource with a different key' do
|
|
449
|
+
before :all do
|
|
450
|
+
@other = @user_model.create(:name => 'dkubb', :age => 33, :comment => @comment)
|
|
451
|
+
@return = @user.eql?(@other)
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it 'returns false' do
|
|
455
|
+
expect(@return).to be(false)
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
describe 'when comparing to a resource with the same repository, key and neither self or the other resource is dirty' do
|
|
460
|
+
before :all do
|
|
461
|
+
rescue_if @skip do
|
|
462
|
+
@other = @user_model.get(*@user.key)
|
|
463
|
+
@return = @user.eql?(@other)
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
it 'returns true' do
|
|
468
|
+
expect(@return).to be(true)
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
describe 'when comparing to a resource with the same repository, key but either self or the other resource is dirty' do
|
|
473
|
+
before :all do
|
|
474
|
+
rescue_if @skip do
|
|
475
|
+
@user.age = 20
|
|
476
|
+
@other = @user_model.get(*@user.key)
|
|
477
|
+
@return = @user.eql?(@other)
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
it 'returns false' do
|
|
482
|
+
expect(@return).to be(false)
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
describe 'when comparing to a resource with the same properties' do
|
|
487
|
+
before :all do
|
|
488
|
+
rescue_if @skip do
|
|
489
|
+
@other = @user_model.new(@user.attributes)
|
|
490
|
+
@return = @user.eql?(@other)
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it 'returns true' do
|
|
495
|
+
expect(@return).to be(true)
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
with_alternate_adapter do
|
|
500
|
+
before :all do
|
|
501
|
+
if @user_model.respond_to?(:auto_migrate!)
|
|
502
|
+
# force the user model to be available in the alternate repository
|
|
503
|
+
@user_model.auto_migrate!(@adapter.name)
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
describe 'when comparing to a resource with a different repository, but the same properties' do
|
|
508
|
+
before :all do
|
|
509
|
+
rescue_if @skip do
|
|
510
|
+
@other = @repository.scope { @user_model.create(@user.attributes) }
|
|
511
|
+
@return = @user.eql?(@other)
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
it 'returns false' do
|
|
516
|
+
expect(@return).to be(false)
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
it { expect(@user).to respond_to(:inspect) }
|
|
523
|
+
|
|
524
|
+
describe '#inspect' do
|
|
525
|
+
before :all do
|
|
526
|
+
rescue_if @skip do
|
|
527
|
+
@user = @user_model.get(*@user.key)
|
|
528
|
+
@inspected = @user.inspect
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it { expect(@inspected).to match(/^#<#{@user_model}/) }
|
|
533
|
+
|
|
534
|
+
it { expect(@inspected).to match(/name="dbussink"/) }
|
|
535
|
+
|
|
536
|
+
it { expect(@inspected).to match(/age=25/) }
|
|
537
|
+
|
|
538
|
+
it { expect(@inspected).to match(/description=<not loaded>/) }
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
it { expect(@user).to respond_to(:key) }
|
|
542
|
+
|
|
543
|
+
describe '#key' do
|
|
544
|
+
before :all do
|
|
545
|
+
rescue_if @skip do
|
|
546
|
+
@key = @user.key
|
|
547
|
+
@user.name = 'dkubb'
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
it { expect(@key).to be_kind_of(Array) }
|
|
552
|
+
|
|
553
|
+
it 'always returns the key value persisted in the back end' do
|
|
554
|
+
expect(@key.first).to eql('dbussink')
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
it { expect(@user.key).to eql(@key) }
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
it { expect(@user).to respond_to(:new?) }
|
|
561
|
+
|
|
562
|
+
describe '#new?' do
|
|
563
|
+
describe 'on an existing record' do
|
|
564
|
+
it { expect(@user).not_to be_new }
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
describe 'on a new record' do
|
|
568
|
+
before { @user = @user_model.new }
|
|
569
|
+
|
|
570
|
+
it { expect(@user).to be_new }
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
it { expect(@user).to respond_to(:reload) }
|
|
575
|
+
|
|
576
|
+
describe '#reload' do
|
|
577
|
+
before do
|
|
578
|
+
# reset the user for each spec
|
|
579
|
+
rescue_if(@skip) do
|
|
580
|
+
@user.update(:name => 'dbussink', :age => 25, :description => 'Test')
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
subject { rescue_if(@skip) { @user.reload } }
|
|
585
|
+
|
|
586
|
+
describe 'on a resource not persisted' do
|
|
587
|
+
before do
|
|
588
|
+
@user.attributes = { :description => 'Changed' }
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
it { is_expected.to be_kind_of(DataMapper::Resource) }
|
|
592
|
+
|
|
593
|
+
it { is_expected.to equal(@user) }
|
|
594
|
+
|
|
595
|
+
it { is_expected.to be_clean }
|
|
596
|
+
|
|
597
|
+
it 'reset the changed attributes' do
|
|
598
|
+
expect(method(:subject)).to change(@user, :description).from('Changed').to('Test')
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
describe 'on a resource where the key is changed, but not persisted' do
|
|
603
|
+
before do
|
|
604
|
+
@user.attributes = { :name => 'dkubb' }
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
it { is_expected.to be_kind_of(DataMapper::Resource) }
|
|
608
|
+
|
|
609
|
+
it { is_expected.to equal(@user) }
|
|
610
|
+
|
|
611
|
+
it { is_expected.to be_clean }
|
|
612
|
+
|
|
613
|
+
it 'resets the changed attributes' do
|
|
614
|
+
expect(method(:subject)).to change(@user, :name).from('dkubb').to('dbussink')
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
describe 'on a resource that is changed outside another resource' do
|
|
619
|
+
before do
|
|
620
|
+
rescue_if @skip do
|
|
621
|
+
@user.dup.update(:description => 'Changed')
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
it { is_expected.to be_kind_of(DataMapper::Resource) }
|
|
626
|
+
|
|
627
|
+
it { is_expected.to equal(@user) }
|
|
628
|
+
|
|
629
|
+
it { is_expected.to be_clean }
|
|
630
|
+
|
|
631
|
+
it 'reloads the resource from the data store' do
|
|
632
|
+
expect(method(:subject)).to change(@user, :description).from('Test').to('Changed')
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
describe 'on an anonymous resource' do
|
|
637
|
+
before do
|
|
638
|
+
rescue_if @skip do
|
|
639
|
+
@user = @user.model.first(fields: [:description])
|
|
640
|
+
expect(@user.description).to eq 'Test'
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
it { is_expected.to be_kind_of(DataMapper::Resource) }
|
|
645
|
+
|
|
646
|
+
it { is_expected.to equal(@user) }
|
|
647
|
+
|
|
648
|
+
it { is_expected.to be_clean }
|
|
649
|
+
|
|
650
|
+
it 'does not reload any attributes' do
|
|
651
|
+
expect(method(:subject)).not_to change(@user, :attributes)
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
it { expect(@user).to respond_to(:readonly?) }
|
|
657
|
+
|
|
658
|
+
describe '#readonly?' do
|
|
659
|
+
describe 'on a new resource' do
|
|
660
|
+
before :all do
|
|
661
|
+
rescue_if @skip do
|
|
662
|
+
@user = @user.model.new
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
it 'returns false' do
|
|
667
|
+
expect(@user.readonly?).to be(false)
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
describe 'on a saved resource' do
|
|
672
|
+
before :all do
|
|
673
|
+
rescue_if @skip do
|
|
674
|
+
expect(@user).to be_saved
|
|
675
|
+
end
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
it 'returns false' do
|
|
679
|
+
expect(@user.readonly?).to be(false)
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
describe 'on a destroyed resource' do
|
|
684
|
+
before :all do
|
|
685
|
+
rescue_if @skip do
|
|
686
|
+
expect(@user.destroy).to be(true)
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
it 'returns true' do
|
|
691
|
+
expect(@user.readonly?).to be(true)
|
|
692
|
+
end
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
describe 'on an anonymous resource' do
|
|
696
|
+
before :all do
|
|
697
|
+
rescue_if @skip do
|
|
698
|
+
# load the user without a key
|
|
699
|
+
@user = @user.model.first(:fields => @user_model.properties - @user_model.key)
|
|
700
|
+
end
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
it 'returns true' do
|
|
704
|
+
expect(@user.readonly?).to be(true)
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
%i(save save!).each do |method|
|
|
710
|
+
it { expect(@user).to respond_to(method) }
|
|
711
|
+
|
|
712
|
+
describe "##{method}" do
|
|
713
|
+
before :all do
|
|
714
|
+
@user_model.class_eval do
|
|
715
|
+
attr_accessor :save_hook_call_count
|
|
716
|
+
|
|
717
|
+
before :save do
|
|
718
|
+
@save_hook_call_count ||= 0
|
|
719
|
+
@save_hook_call_count += 1
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
describe 'on a new, not dirty resource' do
|
|
725
|
+
before :all do
|
|
726
|
+
@user = @user_model.new
|
|
727
|
+
@return = @user.__send__(method)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
it 'returns false' do
|
|
731
|
+
expect(@return).to be(false)
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
it 'calls save hook expected number of times' do
|
|
735
|
+
expect(@user.save_hook_call_count).to be_nil
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
describe 'on a not new, not dirty resource' do
|
|
740
|
+
before :all do
|
|
741
|
+
rescue_if @skip do
|
|
742
|
+
@return = @user.__send__(method)
|
|
743
|
+
end
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
it 'returns true even when resource is not dirty' do
|
|
747
|
+
expect(@return).to be(true)
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
it 'calls save hook expected number of times' do
|
|
751
|
+
expect(@user.save_hook_call_count).to be_nil
|
|
752
|
+
end
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
describe 'on a not new, dirty resource' do
|
|
756
|
+
before :all do
|
|
757
|
+
rescue_if @skip do
|
|
758
|
+
@user.age = 26
|
|
759
|
+
@return = @user.__send__(method)
|
|
760
|
+
end
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
it 'saves a resource succesfully when dirty' do
|
|
764
|
+
expect(@return).to be(true)
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
it 'actually stores the changes to persistent storage' do
|
|
768
|
+
expect(@user.attributes).to eq @user.reload.attributes
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
it 'calls save hook expected number of times' do
|
|
772
|
+
expect(@user.save_hook_call_count).to eq((method == :save) ? 1 : nil)
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
describe 'on a new, invalid resource' do
|
|
777
|
+
before :all do
|
|
778
|
+
@user = @user_model.new(name: nil)
|
|
779
|
+
expect { @user.__send__(method) }.to raise_error(DataMapper::Property::InvalidValueError) do |error|
|
|
780
|
+
expect(error.property).to eq @user_model.properties[:name]
|
|
781
|
+
end
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
it 'calls save hook expected number of times' do
|
|
785
|
+
expect(@user.save_hook_call_count).to eq((method == :save) ? 1 : nil)
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
describe 'on a dirty invalid resource' do
|
|
790
|
+
before :all do
|
|
791
|
+
rescue_if @skip do
|
|
792
|
+
@user.name = nil
|
|
793
|
+
end
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
it 'does not save an invalid resource' do
|
|
797
|
+
expect { @user.__send__(method) }.to(raise_error(DataMapper::Property::InvalidValueError) do |error|
|
|
798
|
+
expect(error.property).to eq @user_model.properties[:name]
|
|
799
|
+
end)
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
it 'calls save hook expected number of times' do
|
|
803
|
+
expect(@user.save_hook_call_count).to eq((method == :save) ? 1 : nil)
|
|
804
|
+
end
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
describe 'with new resources in a has relationship' do
|
|
808
|
+
before do
|
|
809
|
+
rescue_if 'TODO: fix for one to one association', !@user.respond_to?(:comments) do
|
|
810
|
+
@initial_comments = @user.comments.size
|
|
811
|
+
@first_comment = @user.comments.new(:body => "DM is great!")
|
|
812
|
+
@second_comment = @comment_model.new(:user => @user, :body => "is it really?")
|
|
813
|
+
@return = @user.__send__(method)
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
it 'saves resource' do
|
|
818
|
+
pending unless@user.respond_to?(:comments)
|
|
819
|
+
|
|
820
|
+
expect(@return).to be(true)
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
it 'saves the first resource created through new' do
|
|
824
|
+
pending unless @user.respond_to?(:comments)
|
|
825
|
+
|
|
826
|
+
expect(@first_comment.new?).to be(false)
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
it 'saves the correct foreign key for the first resource' do
|
|
830
|
+
pending unless @user.respond_to?(:comments)
|
|
831
|
+
|
|
832
|
+
expect(@first_comment.user).to eql(@user)
|
|
833
|
+
end
|
|
834
|
+
|
|
835
|
+
it 'saves the second resource created through the constructor' do
|
|
836
|
+
pending 'Changing a belongs_to parent adds the resource to the correct association'
|
|
837
|
+
|
|
838
|
+
expect(@second_comment.new?).to be(false)
|
|
839
|
+
end
|
|
840
|
+
|
|
841
|
+
it 'saves the correct foreign key for the second resource' do
|
|
842
|
+
pending unless @user.respond_to?(:comments)
|
|
843
|
+
|
|
844
|
+
expect(@second_comment.user).to eql(@user)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
it 'created 2 extra resources in persistent storage' do
|
|
848
|
+
pending 'Changing a belongs_to parent adds the resource to the correct association'
|
|
849
|
+
|
|
850
|
+
expect(@user.comments.size).to eq @initial_comments + 2
|
|
851
|
+
end
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
describe 'with dirty resources in a has relationship' do
|
|
855
|
+
before :all do
|
|
856
|
+
rescue_if 'TODO: fix for one to one association', !@user.respond_to?(:comments) do
|
|
857
|
+
@first_comment = @user.comments.create(:body => 'DM is great!')
|
|
858
|
+
@second_comment = @comment_model.create(:user => @user, :body => 'is it really?')
|
|
859
|
+
|
|
860
|
+
@first_comment.body = 'It still has rough edges'
|
|
861
|
+
@second_comment.body = 'But these cool specs help fixing that'
|
|
862
|
+
@second_comment.user = @user_model.create(:name => 'dkubb')
|
|
863
|
+
|
|
864
|
+
@return = @user.__send__(method)
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
it 'returns true' do
|
|
869
|
+
pending unless @user.respond_to?(:comments)
|
|
870
|
+
|
|
871
|
+
expect(@return).to be(true)
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
it 'is not dirty' do
|
|
875
|
+
expect(@user).not_to be_dirty
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
it 'has saved the first child resource' do
|
|
879
|
+
pending unless @user.respond_to?(:comments)
|
|
880
|
+
|
|
881
|
+
expect(@first_comment.model.get(*@first_comment.key).body).to eq 'It still has rough edges'
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
it 'has not saved the second child resource' do
|
|
885
|
+
pending unless @user.respond_to?(:comments)
|
|
886
|
+
|
|
887
|
+
expect(@second_comment.model.get(*@second_comment.key).body).to eq 'is it really?'
|
|
888
|
+
end
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
describe 'with a new dependency' do
|
|
892
|
+
before :all do
|
|
893
|
+
@first_comment = @comment_model.new(:body => "DM is great!")
|
|
894
|
+
@first_comment.user = @user_model.new(:name => 'dkubb')
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
it 'does not raise an exception when saving the resource' do
|
|
898
|
+
pending
|
|
899
|
+
|
|
900
|
+
expect { expect(@first_comment.send(method)).to be(false) }.not_to raise_error
|
|
901
|
+
end
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
describe 'with a dirty dependency' do
|
|
905
|
+
before :all do
|
|
906
|
+
rescue_if @skip do
|
|
907
|
+
@user.name = 'dbussink-the-second'
|
|
908
|
+
|
|
909
|
+
@first_comment = @comment_model.new(:body => 'DM is great!')
|
|
910
|
+
@first_comment.user = @user
|
|
911
|
+
|
|
912
|
+
@return = @first_comment.__send__(method)
|
|
913
|
+
end
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
it 'successfully saves the resource' do
|
|
917
|
+
expect(@return).to be(true)
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
it 'does not have a dirty dependency' do
|
|
921
|
+
expect(@user).not_to be_dirty
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
it 'successfully saves the dependency' do
|
|
925
|
+
expect(@user.name).to eq @user_model.get(*@user.key).name
|
|
926
|
+
end
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
describe 'with a new resource and new relations' do
|
|
930
|
+
before :all do
|
|
931
|
+
@article = @article_model.new(:body => "Main")
|
|
932
|
+
rescue_if 'TODO: fix for one to one association', (!@article.respond_to?(:paragraphs)) do
|
|
933
|
+
@paragraph = @article.paragraphs.new(:text => 'Content')
|
|
934
|
+
|
|
935
|
+
@article.__send__(method)
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
it 'is not dirty' do
|
|
940
|
+
pending unless @article.respond_to?(:paragraphs)
|
|
941
|
+
|
|
942
|
+
expect(@article).not_to be_dirty
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
it 'is not dirty' do
|
|
946
|
+
pending unless @article.respond_to?(:paragraphs)
|
|
947
|
+
|
|
948
|
+
expect(@paragraph).not_to be_dirty
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
it 'sets the related resource' do
|
|
952
|
+
pending unless @article.respond_to?(:paragraphs)
|
|
953
|
+
|
|
954
|
+
expect(@paragraph.article).to eq @article
|
|
955
|
+
end
|
|
956
|
+
|
|
957
|
+
it 'sets the foreign key properly' do
|
|
958
|
+
pending unless @article.respond_to?(:paragraphs)
|
|
959
|
+
|
|
960
|
+
expect(@paragraph.article_id).to eq @article.id
|
|
961
|
+
end
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
describe 'with a dirty resource with a changed key' do
|
|
965
|
+
before :all do
|
|
966
|
+
rescue_if @skip do
|
|
967
|
+
@original_key = @user.key
|
|
968
|
+
@user.name = 'dkubb'
|
|
969
|
+
@return = @user.__send__(method)
|
|
970
|
+
end
|
|
971
|
+
end
|
|
972
|
+
|
|
973
|
+
it 'saves a resource successfully when dirty' do
|
|
974
|
+
expect(@return).to be(true)
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
it 'actually stores the changes to persistent storage' do
|
|
978
|
+
expect(@user.name).to eq @user.reload.name
|
|
979
|
+
end
|
|
980
|
+
|
|
981
|
+
it 'updates the identity map' do
|
|
982
|
+
expect(@user.repository.identity_map(@user_model)).to have_key(%w(dkubb))
|
|
983
|
+
end
|
|
984
|
+
|
|
985
|
+
it 'removes the old entry from the identity map' do
|
|
986
|
+
expect(@user.repository.identity_map(@user_model)).not_to have_key(@original_key)
|
|
987
|
+
end
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
describe 'on a new resource with unsaved parent and grandparent' do
|
|
991
|
+
before :all do
|
|
992
|
+
@grandparent = @user_model.new(:name => 'dkubb', :comment => @comment)
|
|
993
|
+
@parent = @user_model.new(:name => 'ashleymoran', :comment => @comment, :referrer => @grandparent)
|
|
994
|
+
@child = @user_model.new(:name => 'mrship', :comment => @comment, :referrer => @parent)
|
|
995
|
+
|
|
996
|
+
@response = @child.__send__(method)
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
it 'returns true' do
|
|
1000
|
+
expect(@response).to be(true)
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
it 'saves the child' do
|
|
1004
|
+
expect(@child).to be_saved
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
it 'saves the parent' do
|
|
1008
|
+
expect(@parent).to be_saved
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
it 'saves the grandparent' do
|
|
1012
|
+
expect(@grandparent).to be_saved
|
|
1013
|
+
end
|
|
1014
|
+
|
|
1015
|
+
it 'relates the child to the parent' do
|
|
1016
|
+
expect(@child.model.get(*@child.key).referrer).to eq @parent
|
|
1017
|
+
end
|
|
1018
|
+
|
|
1019
|
+
it 'relates the parent to the grandparent' do
|
|
1020
|
+
expect(@parent.model.get(*@parent.key).referrer).to eq @grandparent
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
it 'relates the grandparent to nothing' do
|
|
1024
|
+
expect(@grandparent.model.get(*@grandparent.key).referrer).to be_nil
|
|
1025
|
+
end
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
describe 'on a destroyed resource' do
|
|
1029
|
+
before :all do
|
|
1030
|
+
rescue_if @skip do
|
|
1031
|
+
@user.destroy
|
|
1032
|
+
end
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
it 'raises an exception' do
|
|
1036
|
+
expect {
|
|
1037
|
+
@user.__send__(method)
|
|
1038
|
+
}.to raise_error(DataMapper::PersistenceError, "#{@user.model}##{method} cannot be called on a destroyed resource")
|
|
1039
|
+
end
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
describe 'on a record with itself as a parent (circular dependency)' do
|
|
1043
|
+
before :all do
|
|
1044
|
+
rescue_if @skip do
|
|
1045
|
+
@user.parent = @user
|
|
1046
|
+
end
|
|
1047
|
+
end
|
|
1048
|
+
|
|
1049
|
+
it 'does not raise an exception' do
|
|
1050
|
+
expect {
|
|
1051
|
+
expect(@user.__send__(method)).to be(true)
|
|
1052
|
+
}.not_to raise_error(SystemStackError)
|
|
1053
|
+
end
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
describe 'on a record with itself as a child (circular dependency)' do
|
|
1057
|
+
before :all do
|
|
1058
|
+
rescue_if @skip do
|
|
1059
|
+
@user.children = [ @user ]
|
|
1060
|
+
end
|
|
1061
|
+
end
|
|
1062
|
+
|
|
1063
|
+
it 'does not raise an exception' do
|
|
1064
|
+
expect {
|
|
1065
|
+
expect(@user.__send__(method)).to be(true)
|
|
1066
|
+
}.not_to raise_error(SystemStackError)
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
1069
|
+
|
|
1070
|
+
describe 'on a record with a parent as a child (circular dependency)' do
|
|
1071
|
+
before :all do
|
|
1072
|
+
rescue_if @skip do
|
|
1073
|
+
@user.children = [ @user.parent = @user_model.new(:name => 'Parent', :comment => @comment) ]
|
|
1074
|
+
end
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
it 'does not raise an exception' do
|
|
1078
|
+
expect {
|
|
1079
|
+
expect(@user.__send__(method)).to be(true)
|
|
1080
|
+
}.not_to raise_error(SystemStackError)
|
|
1081
|
+
end
|
|
1082
|
+
end
|
|
1083
|
+
end
|
|
1084
|
+
end
|
|
1085
|
+
|
|
1086
|
+
it { expect(@user).to respond_to(:saved?) }
|
|
1087
|
+
|
|
1088
|
+
describe '#saved?' do
|
|
1089
|
+
|
|
1090
|
+
describe 'on an existing record' do
|
|
1091
|
+
it { expect(@user).to be_saved }
|
|
1092
|
+
end
|
|
1093
|
+
|
|
1094
|
+
describe 'on a new record' do
|
|
1095
|
+
|
|
1096
|
+
before { @user = @user_model.new }
|
|
1097
|
+
|
|
1098
|
+
it { expect(@user).not_to be_saved }
|
|
1099
|
+
end
|
|
1100
|
+
|
|
1101
|
+
end
|
|
1102
|
+
|
|
1103
|
+
%i(update update!).each do |method|
|
|
1104
|
+
it { expect(@user).to respond_to(method) }
|
|
1105
|
+
|
|
1106
|
+
describe "##{method}" do
|
|
1107
|
+
describe 'with attributes' do
|
|
1108
|
+
before :all do
|
|
1109
|
+
rescue_if @skip do
|
|
1110
|
+
@attributes = { :description => 'Changed' }
|
|
1111
|
+
@return = @user.__send__(method, @attributes)
|
|
1112
|
+
end
|
|
1113
|
+
end
|
|
1114
|
+
|
|
1115
|
+
it 'returns true' do
|
|
1116
|
+
expect(@return).to be(true)
|
|
1117
|
+
end
|
|
1118
|
+
|
|
1119
|
+
it 'updates attributes of Resource' do
|
|
1120
|
+
@attributes.each { |key, value| expect(@user.__send__(key)).to eq value }
|
|
1121
|
+
end
|
|
1122
|
+
|
|
1123
|
+
it 'persists the changes' do
|
|
1124
|
+
resource = @user_model.get(*@user.key)
|
|
1125
|
+
@attributes.each { |key, value| expect(resource.__send__(key)).to eq value }
|
|
1126
|
+
end
|
|
1127
|
+
end
|
|
1128
|
+
|
|
1129
|
+
describe 'with attributes where one is a parent association' do
|
|
1130
|
+
before :all do
|
|
1131
|
+
rescue_if @skip do
|
|
1132
|
+
@attributes = { :referrer => @user_model.create(:name => 'dkubb', :age => 33, :comment => @comment) }
|
|
1133
|
+
@return = @user.__send__(method, @attributes)
|
|
1134
|
+
end
|
|
1135
|
+
end
|
|
1136
|
+
|
|
1137
|
+
it 'returns true' do
|
|
1138
|
+
expect(@return).to be(true)
|
|
1139
|
+
end
|
|
1140
|
+
|
|
1141
|
+
it 'updates attributes of Resource' do
|
|
1142
|
+
@attributes.each { |key, value| expect(@user.__send__(key)).to eq value }
|
|
1143
|
+
end
|
|
1144
|
+
|
|
1145
|
+
it 'persists the changes' do
|
|
1146
|
+
resource = @user_model.get(*@user.key)
|
|
1147
|
+
@attributes.each { |key, value| expect(resource.__send__(key)).to eq value }
|
|
1148
|
+
end
|
|
1149
|
+
end
|
|
1150
|
+
|
|
1151
|
+
describe 'with attributes where a value is nil for a property that does not allow nil' do
|
|
1152
|
+
before do
|
|
1153
|
+
expect { @user.__send__(method, name: nil) }
|
|
1154
|
+
.to raise_error(DataMapper::Property::InvalidValueError) do |error|
|
|
1155
|
+
expect(error.property).to eq @user_model.properties[:name]
|
|
1156
|
+
end
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
it 'does not persist the changes' do
|
|
1160
|
+
expect(@user.reload.name).not_to be_nil
|
|
1161
|
+
end
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
describe 'on a new resource' do
|
|
1165
|
+
before :all do
|
|
1166
|
+
rescue_if @skip do
|
|
1167
|
+
@user = @user.model.new(@user.attributes)
|
|
1168
|
+
@user.age = 99
|
|
1169
|
+
end
|
|
1170
|
+
end
|
|
1171
|
+
|
|
1172
|
+
it 'raises an exception' do
|
|
1173
|
+
expect {
|
|
1174
|
+
@user.__send__(method, admin: true)
|
|
1175
|
+
}.to raise_error(DataMapper::UpdateConflictError, "#{@user.model}##{method} cannot be called on a new resource")
|
|
1176
|
+
end
|
|
1177
|
+
end
|
|
1178
|
+
|
|
1179
|
+
describe 'on a dirty resource' do
|
|
1180
|
+
before :all do
|
|
1181
|
+
rescue_if @skip do
|
|
1182
|
+
@user.age = 99
|
|
1183
|
+
end
|
|
1184
|
+
end
|
|
1185
|
+
|
|
1186
|
+
it 'raises an exception' do
|
|
1187
|
+
expect {
|
|
1188
|
+
@user.__send__(method, admin: true)
|
|
1189
|
+
}.to raise_error(DataMapper::UpdateConflictError, "#{@user.model}##{method} cannot be called on a dirty resource")
|
|
1190
|
+
end
|
|
1191
|
+
end
|
|
1192
|
+
end
|
|
1193
|
+
end
|
|
1194
|
+
|
|
1195
|
+
describe 'lazy loading' do
|
|
1196
|
+
before :all do
|
|
1197
|
+
rescue_if @skip do
|
|
1198
|
+
@user.name = 'dkubb'
|
|
1199
|
+
@user.age = 33
|
|
1200
|
+
@user.summary = 'Programmer'
|
|
1201
|
+
|
|
1202
|
+
# lazy load the description
|
|
1203
|
+
@user.description
|
|
1204
|
+
end
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
it 'does not overwrite dirty attribute' do
|
|
1208
|
+
expect(@user.age).to eq 33
|
|
1209
|
+
end
|
|
1210
|
+
|
|
1211
|
+
it 'does not overwrite dirty lazy attribute' do
|
|
1212
|
+
expect(@user.summary).to eq 'Programmer'
|
|
1213
|
+
end
|
|
1214
|
+
|
|
1215
|
+
it 'does not overwrite dirty key' do
|
|
1216
|
+
pending
|
|
1217
|
+
|
|
1218
|
+
expect(@user.name).to eq 'dkubb'
|
|
1219
|
+
end
|
|
1220
|
+
end
|
|
1221
|
+
end
|