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,111 @@
|
|
|
1
|
+
share_examples_for 'A Collection supporting Strategic Eager Loading' do
|
|
2
|
+
describe 'using SEL when looping within a loop' do
|
|
3
|
+
before :all do
|
|
4
|
+
@many_to_many = @articles.kind_of?(DataMapper::Associations::ManyToMany::Collection)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
before :all do
|
|
8
|
+
attributes = {}
|
|
9
|
+
|
|
10
|
+
unless @many_to_many
|
|
11
|
+
attributes[:author] = @author
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@revision = @article.revisions.create(attributes.merge(:title => 'Revision'))
|
|
15
|
+
|
|
16
|
+
@new_article = @article_model.create(attributes.merge(:title => 'Sample Article'))
|
|
17
|
+
@new_revision = @new_article.revisions.create(attributes.merge(:title => 'New Revision'))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before :all do
|
|
21
|
+
@original_adapter = @adapter
|
|
22
|
+
|
|
23
|
+
@adapter.singleton_class.class_eval do
|
|
24
|
+
def eql?(other)
|
|
25
|
+
super || self == other
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@adapter = DataMapper::Repository.adapters[@adapter.name] = CounterAdapter.new(@adapter)
|
|
30
|
+
@repository.instance_variable_set(:@adapter, @adapter)
|
|
31
|
+
@articles.instance_variable_get(:@query).instance_variable_set(:@repository, @repository)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
before :all do
|
|
35
|
+
@results = []
|
|
36
|
+
|
|
37
|
+
@articles.each do |article|
|
|
38
|
+
article.revisions.each do |revision|
|
|
39
|
+
@results << [ article, revision ]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
after :all do
|
|
45
|
+
@adapter = @original_adapter
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should only execute the Adapter#read #{loaded ? 'once' : 'twice'}" do
|
|
49
|
+
@adapter.counts[:read].should == (loaded ? 1 : 2)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should return the expected results' do
|
|
53
|
+
# if the collection is already loaded, then when it iterates it will
|
|
54
|
+
# not know about the newly added articles and their revisions
|
|
55
|
+
if loaded
|
|
56
|
+
@results.should == [ [ @article, @revision ] ]
|
|
57
|
+
else
|
|
58
|
+
pending_if 'TODO: make m:m not kick when delegating to the relationship', @many_to_many do
|
|
59
|
+
@results.should == [ [ @article, @revision ], [ @new_article, @new_revision ] ]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
share_examples_for 'A Resource supporting Strategic Eager Loading' do
|
|
67
|
+
describe 'using SEL when inside a Collection' do
|
|
68
|
+
before :all do
|
|
69
|
+
@referrer = @user_model.create(:name => 'Referrer', :comment => @comment)
|
|
70
|
+
|
|
71
|
+
@user.update(:referrer => @referrer)
|
|
72
|
+
|
|
73
|
+
@new_user = @user_model.create(:name => 'Another User', :referrer => @referrer, :comment => @comment)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
before :all do
|
|
77
|
+
@original_adapter = @adapter
|
|
78
|
+
|
|
79
|
+
@adapter.singleton_class.class_eval do
|
|
80
|
+
def eql?(other)
|
|
81
|
+
super || other == self
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
@adapter = DataMapper::Repository.adapters[@adapter.name] = CounterAdapter.new(@adapter)
|
|
86
|
+
@repository.instance_variable_set(:@adapter, @adapter)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
before :all do
|
|
90
|
+
@results = @user_model.all.map do |user|
|
|
91
|
+
[ user, user.referrer ]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# some storage engines return the data in a different order
|
|
95
|
+
@results.sort!
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
after :all do
|
|
99
|
+
@adapter = @original_adapter
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'should only execute the Adapter#read twice' do
|
|
103
|
+
@adapter.counts[:read].should == 2
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'should return the expected results' do
|
|
107
|
+
# results are ordered alphabetically by the User name
|
|
108
|
+
@results.should == [ [ @new_user, @referrer ], [ @referrer, nil ], [ @user, @referrer ] ]
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
share_examples_for 'A semipublic Property' do
|
|
2
|
+
before :all do
|
|
3
|
+
%w[ @type @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
|
+
@property = @type.new(@model, @name, @options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '.new' do
|
|
20
|
+
describe 'when provided no options' do
|
|
21
|
+
it 'should return a Property' do
|
|
22
|
+
@property.should be_kind_of(@type)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'should set the load_as' do
|
|
26
|
+
@property.load_as.should be(@type.load_as)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'should set the model' do
|
|
30
|
+
@property.model.should equal(@model)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should set the options to the default' do
|
|
34
|
+
@property.options.should == @type.options.merge(@options)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
[ :index, :unique_index, :unique, :lazy ].each do |attribute|
|
|
39
|
+
[ true, false, :title, [ :title ] ].each do |value|
|
|
40
|
+
describe "when provided #{(options = { attribute => value }).inspect}" do
|
|
41
|
+
before :all do
|
|
42
|
+
@property = @type.new(@model, @name, @options.merge(options))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'should return a Property' do
|
|
46
|
+
@property.should be_kind_of(@type)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should set the model' do
|
|
50
|
+
@property.model.should equal(@model)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'should set the load_as' do
|
|
54
|
+
@property.load_as.should be(@type.load_as)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should set the options to #{options.inspect}" do
|
|
58
|
+
@property.options.should == @type.options.merge(@options.merge(options))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
[ [], nil ].each do |value|
|
|
64
|
+
describe "when provided #{(invalid_options = { attribute => value }).inspect}" do
|
|
65
|
+
it 'should raise an exception' do
|
|
66
|
+
lambda {
|
|
67
|
+
@type.new(@model, @name, @options.merge(invalid_options))
|
|
68
|
+
}.should raise_error(ArgumentError, "options[#{attribute.inspect}] must be either true, false, a Symbol or an Array of Symbols")
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe '#load' do
|
|
76
|
+
subject { @property.load(@value) }
|
|
77
|
+
|
|
78
|
+
before do
|
|
79
|
+
@property.should_receive(:typecast).with(@value).and_return(@value)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it { should eql(@value) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe "#typecast" do
|
|
86
|
+
describe 'when value is nil' do
|
|
87
|
+
it 'returns value unchanged' do
|
|
88
|
+
@property.typecast(nil).should be(nil)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe 'when value is a Ruby primitive' do
|
|
92
|
+
it 'returns value unchanged' do
|
|
93
|
+
@property.typecast(@value).should == @value
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe '#valid?' do
|
|
100
|
+
describe 'when provided a valid value' do
|
|
101
|
+
it 'should return true' do
|
|
102
|
+
@property.valid?(@value).should be(true)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe 'when provide an invalid value' do
|
|
107
|
+
it 'should return false' do
|
|
108
|
+
@property.valid?(@invalid_value).should be(false)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe 'when provide a nil value when required' do
|
|
113
|
+
it 'should return false' do
|
|
114
|
+
@property = @type.new(@model, @name, @options.merge(:required => true))
|
|
115
|
+
@property.valid?(nil).should be(false)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe 'when provide a nil value when not required' do
|
|
120
|
+
it 'should return false' do
|
|
121
|
+
@property = @type.new(@model, @name, @options.merge(:required => false))
|
|
122
|
+
@property.valid?(nil).should be(true)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe '#assert_valid_value' do
|
|
128
|
+
subject do
|
|
129
|
+
@property.assert_valid_value(value)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
shared_examples_for 'assert_valid_value on invalid value' do
|
|
133
|
+
it 'should raise DataMapper::Property::InvalidValueError' do
|
|
134
|
+
expect { subject }.to(raise_error(DataMapper::Property::InvalidValueError) do |error|
|
|
135
|
+
error.property.should == @property
|
|
136
|
+
end)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
describe 'when provided a valid value' do
|
|
141
|
+
let(:value) { @value }
|
|
142
|
+
|
|
143
|
+
it 'should return true' do
|
|
144
|
+
subject.should be(true)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe 'when provide an invalid value' do
|
|
149
|
+
let(:value) { @invalid_value }
|
|
150
|
+
|
|
151
|
+
it_should_behave_like 'assert_valid_value on invalid value'
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
describe 'when provide a nil value when required' do
|
|
155
|
+
before do
|
|
156
|
+
@property = @type.new(@model, @name, @options.merge(:required => true))
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
let(:value) { nil }
|
|
160
|
+
|
|
161
|
+
it_should_behave_like 'assert_valid_value on invalid value'
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
describe 'when provide a nil value when not required' do
|
|
165
|
+
before do
|
|
166
|
+
@property = @type.new(@model, @name, @options.merge(:required => false))
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
let(:value) { nil }
|
|
170
|
+
|
|
171
|
+
it 'should return true' do
|
|
172
|
+
subject.should be(true)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
shared_examples_for 'DataMapper::Query::Conditions::AbstractComparison' do
|
|
2
|
+
before :all do
|
|
3
|
+
module ::Blog
|
|
4
|
+
class Article
|
|
5
|
+
include DataMapper::Resource
|
|
6
|
+
|
|
7
|
+
property :id, Serial
|
|
8
|
+
property :title, String, :required => true
|
|
9
|
+
|
|
10
|
+
belongs_to :parent, self, :required => false
|
|
11
|
+
has n, :children, self, :inverse => :parent
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
DataMapper.finalize
|
|
16
|
+
|
|
17
|
+
@model = Blog::Article
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before do
|
|
21
|
+
class ::OtherComparison < DataMapper::Query::Conditions::AbstractComparison
|
|
22
|
+
slug :other
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
before do
|
|
27
|
+
@relationship = @model.relationships[:parent]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it { subject.class.should respond_to(:new) }
|
|
31
|
+
|
|
32
|
+
describe '.new' do
|
|
33
|
+
subject { @comparison.class.new(@property, @value) }
|
|
34
|
+
|
|
35
|
+
it { should be_kind_of(@comparison.class) }
|
|
36
|
+
|
|
37
|
+
it { subject.subject.should equal(@property) }
|
|
38
|
+
|
|
39
|
+
it { subject.value.should == @value }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it { subject.class.should respond_to(:slug) }
|
|
43
|
+
|
|
44
|
+
describe '.slug' do
|
|
45
|
+
describe 'with no arguments' do
|
|
46
|
+
subject { @comparison.class.slug }
|
|
47
|
+
|
|
48
|
+
it { should == @slug }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe 'with an argument' do
|
|
52
|
+
subject { @comparison.class.slug(:other) }
|
|
53
|
+
|
|
54
|
+
it { should == :other }
|
|
55
|
+
|
|
56
|
+
# reset the slug
|
|
57
|
+
after { @comparison.class.slug(@slug) }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it { should respond_to(:==) }
|
|
62
|
+
|
|
63
|
+
describe '#==' do
|
|
64
|
+
describe 'when the other AbstractComparison is equal' do
|
|
65
|
+
# artificially modify the object so #== will throw an
|
|
66
|
+
# exception if the equal? branch is not followed when heckling
|
|
67
|
+
before { @comparison.singleton_class.send(:undef_method, :slug) }
|
|
68
|
+
|
|
69
|
+
subject { @comparison == @comparison }
|
|
70
|
+
|
|
71
|
+
it { should be(true) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'when the other AbstractComparison is the same class' do
|
|
75
|
+
subject { @comparison == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value) }
|
|
76
|
+
|
|
77
|
+
it { should be(true) }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe 'when the other AbstractComparison is a different class' do
|
|
81
|
+
subject { @comparison == DataMapper::Query::Conditions::Comparison.new(:other, @property, @value) }
|
|
82
|
+
|
|
83
|
+
it { should be(false) }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe 'when the other AbstractComparison is the same class, with different property' do
|
|
87
|
+
subject { @comparison == DataMapper::Query::Conditions::Comparison.new(@slug, @other_property, @value) }
|
|
88
|
+
|
|
89
|
+
it { should be(false) }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe 'when the other AbstractComparison is the same class, with different value' do
|
|
93
|
+
subject { @comparison == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @other_value) }
|
|
94
|
+
|
|
95
|
+
it { should be(false) }
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it { should respond_to(:eql?) }
|
|
100
|
+
|
|
101
|
+
describe '#eql?' do
|
|
102
|
+
describe 'when the other AbstractComparison is equal' do
|
|
103
|
+
# artificially modify the object so #eql? will throw an
|
|
104
|
+
# exception if the equal? branch is not followed when heckling
|
|
105
|
+
before { @comparison.singleton_class.send(:undef_method, :slug) }
|
|
106
|
+
|
|
107
|
+
subject { @comparison.eql?(@comparison) }
|
|
108
|
+
|
|
109
|
+
it { should be(true) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe 'when the other AbstractComparison is the same class' do
|
|
113
|
+
subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value)) }
|
|
114
|
+
|
|
115
|
+
it { should be(true) }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe 'when the other AbstractComparison is a different class' do
|
|
119
|
+
subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(:other, @property, @value)) }
|
|
120
|
+
|
|
121
|
+
it { should be(false) }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe 'when the other AbstractComparison is the same class, with different property' do
|
|
125
|
+
subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(@slug, @other_property, @value)) }
|
|
126
|
+
|
|
127
|
+
it { should be(false) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe 'when the other AbstractComparison is the same class, with different value' do
|
|
131
|
+
subject { @comparison.eql?(DataMapper::Query::Conditions::Comparison.new(@slug, @property, @other_value)) }
|
|
132
|
+
|
|
133
|
+
it { should be(false) }
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it { should respond_to(:hash) }
|
|
138
|
+
|
|
139
|
+
describe '#hash' do
|
|
140
|
+
subject { @comparison.hash }
|
|
141
|
+
|
|
142
|
+
it 'should match the same AbstractComparison with the same property and value' do
|
|
143
|
+
should == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @value).hash
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'should not match the same AbstractComparison with different property' do
|
|
147
|
+
should_not == DataMapper::Query::Conditions::Comparison.new(@slug, @other_property, @value).hash
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'should not match the same AbstractComparison with different value' do
|
|
151
|
+
should_not == DataMapper::Query::Conditions::Comparison.new(@slug, @property, @other_value).hash
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'should not match a different AbstractComparison with the same property and value' do
|
|
155
|
+
should_not == @other.hash
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'should not match a different AbstractComparison with different property' do
|
|
159
|
+
should_not == @other.class.new(@other_property, @value).hash
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'should not match a different AbstractComparison with different value' do
|
|
163
|
+
should_not == @other.class.new(@property, @other_value).hash
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it { should respond_to(:loaded_value) }
|
|
168
|
+
|
|
169
|
+
describe '#loaded_value' do
|
|
170
|
+
subject { @comparison.loaded_value }
|
|
171
|
+
|
|
172
|
+
it { should == @value }
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it { should respond_to(:parent) }
|
|
176
|
+
|
|
177
|
+
describe '#parent' do
|
|
178
|
+
subject { @comparison.parent }
|
|
179
|
+
|
|
180
|
+
describe 'should be nil by default' do
|
|
181
|
+
it { should be_nil }
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe 'should relate to parent operation' do
|
|
185
|
+
before do
|
|
186
|
+
@operation = DataMapper::Query::Conditions::Operation.new(:and)
|
|
187
|
+
@comparison.parent = @operation
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it { should be_equal(@operation) }
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it { should respond_to(:parent=) }
|
|
195
|
+
|
|
196
|
+
describe '#parent=' do
|
|
197
|
+
before do
|
|
198
|
+
@operation = DataMapper::Query::Conditions::Operation.new(:and)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
subject { @comparison.parent = @operation }
|
|
202
|
+
|
|
203
|
+
it { should equal(@operation) }
|
|
204
|
+
|
|
205
|
+
it 'should change the parent' do
|
|
206
|
+
method(:subject).should change(@comparison, :parent).
|
|
207
|
+
from(nil).
|
|
208
|
+
to(@operation)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it { should respond_to(:property?) }
|
|
213
|
+
|
|
214
|
+
describe '#property?' do
|
|
215
|
+
subject { @comparison.property? }
|
|
216
|
+
|
|
217
|
+
it { should be(true) }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it { should respond_to(:slug) }
|
|
221
|
+
|
|
222
|
+
describe '#slug' do
|
|
223
|
+
subject { @comparison.slug }
|
|
224
|
+
|
|
225
|
+
it { should == @slug }
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it { should respond_to(:subject) }
|
|
229
|
+
|
|
230
|
+
describe '#subject' do
|
|
231
|
+
subject { @comparison.subject }
|
|
232
|
+
|
|
233
|
+
it { should be_equal(@property) }
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it { should respond_to(:valid?) }
|
|
237
|
+
|
|
238
|
+
describe '#valid?' do
|
|
239
|
+
subject { @comparison.valid? }
|
|
240
|
+
|
|
241
|
+
describe 'when the value is valid for the subject' do
|
|
242
|
+
it { should be(true) }
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
describe 'when the value is not valid for the subject' do
|
|
246
|
+
before do
|
|
247
|
+
@comparison = DataMapper::Query::Conditions::Comparison.new(@slug, @property, nil)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it { should be(false) }
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it { should respond_to(:value) }
|
|
255
|
+
|
|
256
|
+
describe '#value' do
|
|
257
|
+
subject { @comparison.value }
|
|
258
|
+
|
|
259
|
+
it { should == @value }
|
|
260
|
+
end
|
|
261
|
+
end
|