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