dm-core 0.9.11 → 0.10.0
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 +17 -14
- data/.gitignore +3 -1
- data/FAQ +6 -5
- data/History.txt +5 -50
- data/Manifest.txt +66 -76
- data/QUICKLINKS +1 -1
- data/README.txt +21 -15
- data/Rakefile +6 -7
- data/SPECS +2 -29
- data/TODO +1 -1
- data/deps.rip +2 -0
- data/dm-core.gemspec +11 -15
- data/lib/dm-core.rb +105 -110
- data/lib/dm-core/adapters.rb +135 -16
- data/lib/dm-core/adapters/abstract_adapter.rb +251 -181
- data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
- data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
- data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
- data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
- data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
- data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
- data/lib/dm-core/associations/many_to_many.rb +372 -90
- data/lib/dm-core/associations/many_to_one.rb +220 -73
- data/lib/dm-core/associations/one_to_many.rb +319 -255
- data/lib/dm-core/associations/one_to_one.rb +66 -53
- data/lib/dm-core/associations/relationship.rb +561 -156
- data/lib/dm-core/collection.rb +1101 -379
- data/lib/dm-core/core_ext/kernel.rb +12 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +4 -34
- data/lib/dm-core/migrations.rb +1283 -0
- data/lib/dm-core/model.rb +570 -369
- data/lib/dm-core/model/descendant_set.rb +81 -0
- data/lib/dm-core/model/hook.rb +45 -0
- data/lib/dm-core/model/is.rb +32 -0
- data/lib/dm-core/model/property.rb +247 -0
- data/lib/dm-core/model/relationship.rb +335 -0
- data/lib/dm-core/model/scope.rb +90 -0
- data/lib/dm-core/property.rb +808 -273
- data/lib/dm-core/property_set.rb +141 -98
- data/lib/dm-core/query.rb +1037 -483
- data/lib/dm-core/query/conditions/comparison.rb +872 -0
- data/lib/dm-core/query/conditions/operation.rb +221 -0
- data/lib/dm-core/query/direction.rb +43 -0
- data/lib/dm-core/query/operator.rb +84 -0
- data/lib/dm-core/query/path.rb +138 -0
- data/lib/dm-core/query/sort.rb +45 -0
- data/lib/dm-core/repository.rb +210 -94
- data/lib/dm-core/resource.rb +641 -421
- data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
- data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
- data/lib/dm-core/support/chainable.rb +22 -0
- data/lib/dm-core/support/deprecate.rb +12 -0
- data/lib/dm-core/support/logger.rb +13 -0
- data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
- data/lib/dm-core/transaction.rb +333 -92
- data/lib/dm-core/type.rb +98 -60
- data/lib/dm-core/types/boolean.rb +1 -1
- data/lib/dm-core/types/discriminator.rb +34 -20
- data/lib/dm-core/types/object.rb +7 -4
- data/lib/dm-core/types/paranoid_boolean.rb +11 -9
- data/lib/dm-core/types/paranoid_datetime.rb +11 -9
- data/lib/dm-core/types/serial.rb +3 -3
- data/lib/dm-core/types/text.rb +3 -4
- data/lib/dm-core/version.rb +1 -1
- data/script/performance.rb +102 -109
- data/script/profile.rb +169 -38
- data/spec/lib/adapter_helpers.rb +105 -0
- data/spec/lib/collection_helpers.rb +18 -0
- data/spec/lib/counter_adapter.rb +34 -0
- data/spec/lib/pending_helpers.rb +27 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
- data/spec/public/associations/many_to_many_spec.rb +193 -0
- data/spec/public/associations/many_to_one_spec.rb +73 -0
- data/spec/public/associations/one_to_many_spec.rb +77 -0
- data/spec/public/associations/one_to_one_spec.rb +156 -0
- data/spec/public/collection_spec.rb +65 -0
- data/spec/public/migrations_spec.rb +359 -0
- data/spec/public/model/relationship_spec.rb +924 -0
- data/spec/public/model_spec.rb +159 -0
- data/spec/public/property_spec.rb +829 -0
- data/spec/public/resource_spec.rb +71 -0
- data/spec/public/sel_spec.rb +44 -0
- data/spec/public/setup_spec.rb +145 -0
- data/spec/public/shared/association_collection_shared_spec.rb +317 -0
- data/spec/public/shared/collection_shared_spec.rb +1670 -0
- data/spec/public/shared/finder_shared_spec.rb +1619 -0
- data/spec/public/shared/resource_shared_spec.rb +924 -0
- data/spec/public/shared/sel_shared_spec.rb +112 -0
- data/spec/public/transaction_spec.rb +129 -0
- data/spec/public/types/discriminator_spec.rb +130 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
- data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
- data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
- data/spec/semipublic/associations/relationship_spec.rb +194 -0
- data/spec/semipublic/associations_spec.rb +177 -0
- data/spec/semipublic/collection_spec.rb +142 -0
- data/spec/semipublic/property_spec.rb +61 -0
- data/spec/semipublic/query/conditions_spec.rb +528 -0
- data/spec/semipublic/query/path_spec.rb +443 -0
- data/spec/semipublic/query_spec.rb +2626 -0
- data/spec/semipublic/resource_spec.rb +47 -0
- data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
- data/spec/spec.opts +3 -1
- data/spec/spec_helper.rb +80 -57
- data/tasks/ci.rb +19 -31
- data/tasks/dm.rb +43 -48
- data/tasks/doc.rb +8 -11
- data/tasks/gemspec.rb +5 -5
- data/tasks/hoe.rb +15 -16
- data/tasks/install.rb +8 -10
- metadata +74 -111
- data/lib/dm-core/associations.rb +0 -207
- data/lib/dm-core/associations/relationship_chain.rb +0 -81
- data/lib/dm-core/auto_migrations.rb +0 -105
- data/lib/dm-core/dependency_queue.rb +0 -32
- data/lib/dm-core/hook.rb +0 -11
- data/lib/dm-core/is.rb +0 -16
- data/lib/dm-core/logger.rb +0 -232
- data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
- data/lib/dm-core/migrator.rb +0 -29
- data/lib/dm-core/scope.rb +0 -58
- data/lib/dm-core/support.rb +0 -7
- data/lib/dm-core/support/array.rb +0 -13
- data/lib/dm-core/support/assertions.rb +0 -8
- data/lib/dm-core/support/errors.rb +0 -23
- data/lib/dm-core/support/kernel.rb +0 -11
- data/lib/dm-core/support/symbol.rb +0 -41
- data/lib/dm-core/type_map.rb +0 -80
- data/lib/dm-core/types.rb +0 -19
- data/script/all +0 -4
- data/spec/integration/association_spec.rb +0 -1382
- data/spec/integration/association_through_spec.rb +0 -203
- data/spec/integration/associations/many_to_many_spec.rb +0 -449
- data/spec/integration/associations/many_to_one_spec.rb +0 -163
- data/spec/integration/associations/one_to_many_spec.rb +0 -188
- data/spec/integration/auto_migrations_spec.rb +0 -413
- data/spec/integration/collection_spec.rb +0 -1073
- data/spec/integration/data_objects_adapter_spec.rb +0 -32
- data/spec/integration/dependency_queue_spec.rb +0 -46
- data/spec/integration/model_spec.rb +0 -197
- data/spec/integration/mysql_adapter_spec.rb +0 -85
- data/spec/integration/postgres_adapter_spec.rb +0 -731
- data/spec/integration/property_spec.rb +0 -253
- data/spec/integration/query_spec.rb +0 -514
- data/spec/integration/repository_spec.rb +0 -61
- data/spec/integration/resource_spec.rb +0 -513
- data/spec/integration/sqlite3_adapter_spec.rb +0 -352
- data/spec/integration/sti_spec.rb +0 -273
- data/spec/integration/strategic_eager_loading_spec.rb +0 -156
- data/spec/integration/transaction_spec.rb +0 -75
- data/spec/integration/type_spec.rb +0 -275
- data/spec/lib/logging_helper.rb +0 -18
- data/spec/lib/mock_adapter.rb +0 -27
- data/spec/lib/model_loader.rb +0 -100
- data/spec/lib/publicize_methods.rb +0 -28
- data/spec/models/content.rb +0 -16
- data/spec/models/vehicles.rb +0 -34
- data/spec/models/zoo.rb +0 -48
- data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
- data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
- data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
- data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
- data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
- data/spec/unit/associations/many_to_many_spec.rb +0 -32
- data/spec/unit/associations/many_to_one_spec.rb +0 -159
- data/spec/unit/associations/one_to_many_spec.rb +0 -393
- data/spec/unit/associations/one_to_one_spec.rb +0 -7
- data/spec/unit/associations/relationship_spec.rb +0 -71
- data/spec/unit/associations_spec.rb +0 -242
- data/spec/unit/auto_migrations_spec.rb +0 -111
- data/spec/unit/collection_spec.rb +0 -182
- data/spec/unit/data_mapper_spec.rb +0 -35
- data/spec/unit/identity_map_spec.rb +0 -126
- data/spec/unit/is_spec.rb +0 -80
- data/spec/unit/migrator_spec.rb +0 -33
- data/spec/unit/model_spec.rb +0 -321
- data/spec/unit/naming_conventions_spec.rb +0 -36
- data/spec/unit/property_set_spec.rb +0 -90
- data/spec/unit/property_spec.rb +0 -753
- data/spec/unit/query_spec.rb +0 -571
- data/spec/unit/repository_spec.rb +0 -93
- data/spec/unit/resource_spec.rb +0 -649
- data/spec/unit/scope_spec.rb +0 -142
- data/spec/unit/transaction_spec.rb +0 -493
- data/spec/unit/type_map_spec.rb +0 -114
- data/spec/unit/type_spec.rb +0 -119
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
# run the specs once with a loaded collection and once not
|
|
4
|
+
[ false, true ].each do |loaded|
|
|
5
|
+
describe DataMapper::Collection do
|
|
6
|
+
extend DataMapper::Spec::CollectionHelpers::GroupMethods
|
|
7
|
+
|
|
8
|
+
self.loaded = loaded
|
|
9
|
+
|
|
10
|
+
before :all do
|
|
11
|
+
module ::Blog
|
|
12
|
+
class Article
|
|
13
|
+
include DataMapper::Resource
|
|
14
|
+
|
|
15
|
+
property :id, Serial
|
|
16
|
+
property :title, String
|
|
17
|
+
property :content, Text
|
|
18
|
+
property :subtitle, String
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@article_model = Blog::Article
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
supported_by :all do
|
|
26
|
+
before :all do
|
|
27
|
+
@article_repository = @repository
|
|
28
|
+
@articles_query = DataMapper::Query.new(@article_repository, @article_model, :title => 'Sample Article')
|
|
29
|
+
|
|
30
|
+
@article = @article_model.create(:title => 'Sample Article', :content => 'Sample')
|
|
31
|
+
|
|
32
|
+
@articles = @article_model.all(@articles_query)
|
|
33
|
+
|
|
34
|
+
@articles.entries if loaded
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it { DataMapper::Collection.should respond_to(:new) }
|
|
38
|
+
|
|
39
|
+
describe '.new' do
|
|
40
|
+
describe 'with resources' do
|
|
41
|
+
before :all do
|
|
42
|
+
@return = @collection = DataMapper::Collection.new(@articles_query, [ @article ])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'should return a Collection' do
|
|
46
|
+
@return.should be_kind_of(DataMapper::Collection)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should be loaded' do
|
|
50
|
+
@return.should be_loaded
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'should contain the article' do
|
|
54
|
+
@collection.should == [ @article ]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe 'with no resources' do
|
|
59
|
+
before :all do
|
|
60
|
+
@return = @collection = DataMapper::Collection.new(@articles_query)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'should return a Collection' do
|
|
64
|
+
@return.should be_kind_of(DataMapper::Collection)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'should not be loaded' do
|
|
68
|
+
@return.should_not be_loaded
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'should contain the article' do
|
|
72
|
+
@collection.should == [ @article ]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it { @articles.should respond_to(:properties) }
|
|
78
|
+
|
|
79
|
+
describe '#properties' do
|
|
80
|
+
before :all do
|
|
81
|
+
@return = @properties = @articles.properties
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should return a PropertySet' do
|
|
85
|
+
@return.should be_kind_of(DataMapper::PropertySet)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'should be expected properties' do
|
|
89
|
+
@properties.to_a.should == @articles_query.fields
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it { @articles.should respond_to(:query) }
|
|
94
|
+
|
|
95
|
+
describe '#query' do
|
|
96
|
+
before :all do
|
|
97
|
+
@return = @articles.query
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should return a Query' do
|
|
101
|
+
@return.should be_kind_of(DataMapper::Query)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should return expected Query' do
|
|
105
|
+
@return.should eql(@articles_query)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it { @articles.should respond_to(:relationships) }
|
|
110
|
+
|
|
111
|
+
describe '#relationships' do
|
|
112
|
+
before :all do
|
|
113
|
+
@return = @relationships = @articles.relationships
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'should return a Hash' do
|
|
117
|
+
@return.should be_kind_of(Hash)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should return expected Hash' do
|
|
121
|
+
@return.should equal(@article_model.relationships(@article_repository.name))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it { @articles.should respond_to(:repository) }
|
|
126
|
+
|
|
127
|
+
describe '#repository' do
|
|
128
|
+
before :all do
|
|
129
|
+
@return = @repository = @articles.repository
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'should return a Repository' do
|
|
133
|
+
@return.should be_kind_of(DataMapper::Repository)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'should be expected Repository' do
|
|
137
|
+
@repository.should == @article_repository
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe DataMapper::Property do
|
|
4
|
+
before :all do
|
|
5
|
+
module ::Blog
|
|
6
|
+
class Author
|
|
7
|
+
include DataMapper::Resource
|
|
8
|
+
|
|
9
|
+
property :name, String, :key => true
|
|
10
|
+
property :alias, String
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#valid?' do
|
|
16
|
+
describe 'when provided a valid value' do
|
|
17
|
+
it 'should return true' do
|
|
18
|
+
Blog::Author.properties[:name].valid?('Dan Kubb').should be_true
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'when provide an invalid value' do
|
|
23
|
+
it 'should return false' do
|
|
24
|
+
Blog::Author.properties[:name].valid?(1).should be_false
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe 'when provide a nil value when not nullable' do
|
|
29
|
+
it 'should return false' do
|
|
30
|
+
Blog::Author.properties[:name].valid?(nil).should be_false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe 'when provide a nil value when nullable' do
|
|
35
|
+
it 'should return false' do
|
|
36
|
+
Blog::Author.properties[:alias].valid?(nil).should be_true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe 'override property definition in other repository' do
|
|
42
|
+
before(:all) do
|
|
43
|
+
module ::Blog
|
|
44
|
+
class Author
|
|
45
|
+
repository(:other) do
|
|
46
|
+
property :name, String, :key => true, :field => 'other_name'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should return property options in other repository' do
|
|
53
|
+
::Blog::Author.properties(:other)[:name].options[:field].should == 'other_name'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'should return property options in default repository' do
|
|
57
|
+
::Blog::Author.properties[:name].options[:field].should be_nil
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
include DataMapper::Query::Conditions
|
|
4
|
+
|
|
5
|
+
module ComparisonSpecHelpers
|
|
6
|
+
|
|
7
|
+
def match(record)
|
|
8
|
+
ComparisonMatcher.new(record)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ComparisonMatcher
|
|
12
|
+
|
|
13
|
+
def initialize(record)
|
|
14
|
+
@record = record
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def matches?(comparison)
|
|
18
|
+
@comparison = comparison
|
|
19
|
+
comparison.matches?(@record)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def failure_message
|
|
23
|
+
"Expected #{@comparison.inspect} to match #{@record.inspect}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def negative_failure_message
|
|
27
|
+
"Expected #{@comparison.inspect} to NOT match #{@record.inspect}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe DataMapper::Query::Conditions do
|
|
35
|
+
|
|
36
|
+
include ComparisonSpecHelpers
|
|
37
|
+
|
|
38
|
+
before :all do
|
|
39
|
+
class ::Mass < DataMapper::Type
|
|
40
|
+
primitive Integer
|
|
41
|
+
|
|
42
|
+
def self.load(value, property)
|
|
43
|
+
{ 1 => 'Small', 2 => 'Large', 3 => 'XLarge' }[value]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.dump(value, property)
|
|
47
|
+
{ 'Small' => 1, 'Large' => 2, 'XLarge' => 3 }[value]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class ::Heffalump
|
|
52
|
+
include DataMapper::Resource
|
|
53
|
+
|
|
54
|
+
property :id, Serial
|
|
55
|
+
property :color, String
|
|
56
|
+
property :num_spots, Integer
|
|
57
|
+
property :striped, Boolean
|
|
58
|
+
property :mass, Mass, :default => 'Large', :nullable => false
|
|
59
|
+
|
|
60
|
+
belongs_to :parent, Heffalump
|
|
61
|
+
|
|
62
|
+
# Heffalumps are surprisingly picky when it comes to choosing friends --
|
|
63
|
+
# they greatly prefer the company of similarly sized beasts. :)
|
|
64
|
+
has n, :mass_mates, Heffalump, :child_key => [:mass], :parent_key => [:mass]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
@heff1 = Heffalump.new(:id => 1, :num_spots => 1, :color => 'green', :striped => true, :mass => 'Small')
|
|
68
|
+
@heff2 = Heffalump.new(:id => 2, :num_spots => 2, :color => 'green', :striped => false, :mass => 'Large', :parent => @heff1)
|
|
69
|
+
@heff3 = Heffalump.new(:id => 3, :num_spots => 3, :color => 'blue', :striped => false, :mass => 'XLarge', :parent => @heff2)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe 'Operations' do
|
|
73
|
+
before do
|
|
74
|
+
@comp1 = Comparison.new(:eql, Heffalump.num_spots, 1)
|
|
75
|
+
@comp2 = Comparison.new(:eql, Heffalump.color, 'green')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should initialize an AbstractOperation object' do
|
|
79
|
+
op = Operation.new(:and)
|
|
80
|
+
op.should be_kind_of(AbstractOperation)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
{
|
|
84
|
+
:and => AndOperation,
|
|
85
|
+
:or => OrOperation,
|
|
86
|
+
:not => NotOperation
|
|
87
|
+
}.each do |operand, klass|
|
|
88
|
+
it "should initialize as #{klass} for the #{operand} operator" do
|
|
89
|
+
op = Operation.new(operand)
|
|
90
|
+
op.should be_kind_of(klass)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should set the remaining args in @operands' do
|
|
95
|
+
op = Operation.new(:and, @comp1, @comp2)
|
|
96
|
+
op.operands.should == [@comp1, @comp2]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should have operands be empty of no operands are provided' do
|
|
100
|
+
op = Operation.new(:and)
|
|
101
|
+
op.operands.should == []
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe 'NotOperation' do
|
|
105
|
+
before do
|
|
106
|
+
@op = Operation.new(:not, @comp1)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'should not allow more than one operand' do
|
|
110
|
+
lambda {
|
|
111
|
+
Operation.new(:not, @comp1, @comp2)
|
|
112
|
+
}.should raise_error(InvalidOperation)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'should negate the comparison' do
|
|
116
|
+
@comp1.should match(@heff1)
|
|
117
|
+
@op.should_not match(@heff1)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe 'AndOperation' do
|
|
122
|
+
before do
|
|
123
|
+
@op = Operation.new(:and, @comp1, @comp2)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should match if all comparisons match' do
|
|
127
|
+
@comp1.should match(@heff1)
|
|
128
|
+
@comp2.should match(@heff1)
|
|
129
|
+
|
|
130
|
+
@op.should match(@heff1)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'should not match of any of the comparisons does not match' do
|
|
134
|
+
@comp1.should_not match(@heff2)
|
|
135
|
+
|
|
136
|
+
@op.should_not match(@heff2)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
describe 'OrOperation' do
|
|
141
|
+
before do
|
|
142
|
+
@op = Operation.new(:or, @comp1, @comp2)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'should match if any of the comparisons match' do
|
|
146
|
+
@comp1.should_not match(@heff2)
|
|
147
|
+
@comp2.should match(@heff2)
|
|
148
|
+
|
|
149
|
+
@op.should match(@heff2)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'should not match if none of the comparisons match' do
|
|
153
|
+
@comp1.should_not match(@heff3)
|
|
154
|
+
@comp2.should_not match(@heff3)
|
|
155
|
+
|
|
156
|
+
@op.should_not match(@heff3)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
describe 'Comparisons' do
|
|
162
|
+
it 'should initialize an AbstractComparison object' do
|
|
163
|
+
comp = Comparison.new(:eql, Heffalump.num_spots, 1)
|
|
164
|
+
comp.should be_kind_of(AbstractComparison)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
{
|
|
168
|
+
:eql => EqualToComparison,
|
|
169
|
+
:gt => GreaterThanComparison,
|
|
170
|
+
:gte => GreaterThanOrEqualToComparison,
|
|
171
|
+
:lt => LessThanComparison,
|
|
172
|
+
:lte => LessThanOrEqualToComparison,
|
|
173
|
+
:regexp => RegexpComparison
|
|
174
|
+
}.each do |slug, klass|
|
|
175
|
+
it "should initialize as #{klass} for the #{slug} comparator" do
|
|
176
|
+
comp = Comparison.new(slug, Heffalump.num_spots, 2)
|
|
177
|
+
comp.should be_kind_of(klass)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'should initialize as InclusionComparison for the :in comparator' do
|
|
182
|
+
comp = Comparison.new(:in, Heffalump.num_spots, [ 2 ])
|
|
183
|
+
comp.should be_kind_of(InclusionComparison)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe 'EqualToComparison' do
|
|
187
|
+
describe 'with a value matching the property primitive' do
|
|
188
|
+
before :all do
|
|
189
|
+
@comp = Comparison.new(:eql, Heffalump.striped, false)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it_should_behave_like 'A valid query condition'
|
|
193
|
+
|
|
194
|
+
it 'should match records that equal the given value' do
|
|
195
|
+
@comp.should match(@heff2)
|
|
196
|
+
@comp.should match(@heff3)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'should not match records that do not equal the given value' do
|
|
200
|
+
@comp.should_not match(@heff1)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
describe 'with a value coerced into the property primitive' do
|
|
205
|
+
before :all do
|
|
206
|
+
@comp = Comparison.new(:eql, Heffalump.striped, 'false')
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it_should_behave_like 'A valid query condition'
|
|
210
|
+
|
|
211
|
+
it 'should match records that equal the given value' do
|
|
212
|
+
@comp.should match(@heff2)
|
|
213
|
+
@comp.should match(@heff3)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it 'should not match records that do not equal the given value' do
|
|
217
|
+
@comp.should_not match(@heff1)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
describe 'with a value from a custom type' do
|
|
222
|
+
before :all do
|
|
223
|
+
@comp = Comparison.new(:eql, Heffalump.mass, 'Large')
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it_should_behave_like 'A valid query condition'
|
|
227
|
+
|
|
228
|
+
it 'should match records that equal the given value' do
|
|
229
|
+
@comp.should match(@heff2)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it 'should not match records that do not equal the given value' do
|
|
233
|
+
@comp.should_not match(@heff1)
|
|
234
|
+
@comp.should_not match(@heff3)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
describe 'with a relationship subject' do
|
|
239
|
+
before :all do
|
|
240
|
+
@comp = Comparison.new(:eql, Heffalump.relationships[:parent], @heff1)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it_should_behave_like 'A valid query condition'
|
|
244
|
+
|
|
245
|
+
it 'should match records that equal the given value' do
|
|
246
|
+
@comp.should match(@heff2)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it 'should not match records that do not equal the given value' do
|
|
250
|
+
@comp.should_not match(@heff1)
|
|
251
|
+
@comp.should_not match(@heff3)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
describe 'with a relationship subject using a custom type key' do
|
|
256
|
+
before :all do
|
|
257
|
+
@comp = Comparison.new(:eql, Heffalump.relationships[:mass_mates], @heff1)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it_should_behave_like 'A valid query condition'
|
|
261
|
+
|
|
262
|
+
it 'should match records that equal the given value' do
|
|
263
|
+
@comp.should match(Heffalump.new(:id => 4, :mass => 'Small'))
|
|
264
|
+
@comp.should match(@heff1)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it 'should not match records that do not equal the given value' do
|
|
268
|
+
@comp.should_not match(@heff2)
|
|
269
|
+
@comp.should_not match(@heff3)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
describe 'InclusionComparison' do
|
|
275
|
+
describe 'with a value matching the property primitive' do
|
|
276
|
+
before :all do
|
|
277
|
+
@comp = Comparison.new(:in, Heffalump.num_spots, 1..2)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it_should_behave_like 'A valid query condition'
|
|
281
|
+
|
|
282
|
+
it 'should match records that equal the given value' do
|
|
283
|
+
@comp.should match(@heff1)
|
|
284
|
+
@comp.should match(@heff2)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'should not match records that do not equal the given value' do
|
|
288
|
+
@comp.should_not match(@heff3)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
describe 'with a value coerced into the property primitive' do
|
|
293
|
+
before :all do
|
|
294
|
+
@comp = Comparison.new(:in, Heffalump.num_spots, '1'..'2')
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it_should_behave_like 'A valid query condition'
|
|
298
|
+
|
|
299
|
+
it 'should match records that equal the given value' do
|
|
300
|
+
@comp.should match(@heff1)
|
|
301
|
+
@comp.should match(@heff2)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it 'should not match records that do not equal the given value' do
|
|
305
|
+
@comp.should_not match(@heff3)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
describe 'with a value from a custom type' do
|
|
310
|
+
before :all do
|
|
311
|
+
@comp = Comparison.new(:in, Heffalump.mass, ['Small', 'Large'])
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it_should_behave_like 'A valid query condition'
|
|
315
|
+
|
|
316
|
+
it 'should match records that equal the given value' do
|
|
317
|
+
@comp.should match(@heff1)
|
|
318
|
+
@comp.should match(@heff2)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it 'should not match records that do not equal the given value' do
|
|
322
|
+
@comp.should_not match(@heff3)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
describe 'with a relationship subject' do
|
|
327
|
+
before :all do
|
|
328
|
+
@comp = Comparison.new(:in, Heffalump.relationships[:parent], [@heff1, @heff2])
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
it_should_behave_like 'A valid query condition'
|
|
332
|
+
|
|
333
|
+
it 'should match records that equal the given value' do
|
|
334
|
+
@comp.should match(@heff2)
|
|
335
|
+
@comp.should match(@heff3)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it 'should not match records that do not equal the given value' do
|
|
339
|
+
@comp.should_not match(@heff1)
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
describe 'with a relationship subject using a custom type key' do
|
|
344
|
+
before :all do
|
|
345
|
+
@comp = Comparison.new(:in, Heffalump.relationships[:mass_mates], [@heff1, @heff2])
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it_should_behave_like 'A valid query condition'
|
|
349
|
+
|
|
350
|
+
it 'should match records that equal the given value' do
|
|
351
|
+
@comp.should match(Heffalump.new(:mass => 'Small'))
|
|
352
|
+
@comp.should match(Heffalump.new(:mass => 'Large'))
|
|
353
|
+
@comp.should match(@heff1)
|
|
354
|
+
@comp.should match(@heff2)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
it 'should not match records that do not equal the given value' do
|
|
358
|
+
@comp.should_not match(@heff3)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
describe 'GreaterThanComparison' do
|
|
364
|
+
describe 'with a value matching the property primitive' do
|
|
365
|
+
before :all do
|
|
366
|
+
@comp = Comparison.new(:gt, Heffalump.num_spots, 2)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it_should_behave_like 'A valid query condition'
|
|
370
|
+
|
|
371
|
+
it 'should match records that are greater than the given value' do
|
|
372
|
+
@comp.should match(@heff3)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it 'should not match records that are not greater than the given value' do
|
|
376
|
+
@comp.should_not match(@heff1)
|
|
377
|
+
@comp.should_not match(@heff2)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
describe 'with a value coerced into the property primitive' do
|
|
382
|
+
before :all do
|
|
383
|
+
@comp = Comparison.new(:gt, Heffalump.num_spots, '2')
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
it_should_behave_like 'A valid query condition'
|
|
387
|
+
|
|
388
|
+
it 'should match records that are greater than the given value' do
|
|
389
|
+
@comp.should match(@heff3)
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
it 'should not match records that are not greater than the given value' do
|
|
393
|
+
@comp.should_not match(@heff1)
|
|
394
|
+
@comp.should_not match(@heff2)
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
describe 'GreaterThanOrEqualToComparison' do
|
|
400
|
+
describe 'with a value matching the property primitive' do
|
|
401
|
+
before :all do
|
|
402
|
+
@comp = Comparison.new(:gte, Heffalump.num_spots, 2)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it_should_behave_like 'A valid query condition'
|
|
406
|
+
|
|
407
|
+
it 'should match records that are greater than or equal to the given value' do
|
|
408
|
+
@comp.should match(@heff2)
|
|
409
|
+
@comp.should match(@heff3)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it 'should not match records that are not greater than or equal to the given value' do
|
|
413
|
+
@comp.should_not match(@heff1)
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
describe 'with a value coerced into the property primitive' do
|
|
418
|
+
before :all do
|
|
419
|
+
@comp = Comparison.new(:gte, Heffalump.num_spots, 2.0)
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
it_should_behave_like 'A valid query condition'
|
|
423
|
+
|
|
424
|
+
it 'should match records that are greater than or equal to the given value' do
|
|
425
|
+
@comp.should match(@heff2)
|
|
426
|
+
@comp.should match(@heff3)
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
it 'should not match records that are not greater than or equal to the given value' do
|
|
430
|
+
@comp.should_not match(@heff1)
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
describe 'LessThanComparison' do
|
|
436
|
+
describe 'with a value matching the property primitive' do
|
|
437
|
+
before :all do
|
|
438
|
+
@comp = Comparison.new(:lt, Heffalump.num_spots, 2)
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it_should_behave_like 'A valid query condition'
|
|
442
|
+
|
|
443
|
+
it 'should match records that are less than the given value' do
|
|
444
|
+
@comp.should match(@heff1)
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it 'should not match records that are not less than the given value' do
|
|
448
|
+
@comp.should_not match(@heff2)
|
|
449
|
+
@comp.should_not match(@heff3)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
describe 'with a value coerced into the property primitive' do
|
|
454
|
+
before :all do
|
|
455
|
+
@comp = Comparison.new(:lt, Heffalump.num_spots, BigDecimal('2.0'))
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
it_should_behave_like 'A valid query condition'
|
|
459
|
+
|
|
460
|
+
it 'should match records that are less than the given value' do
|
|
461
|
+
@comp.should match(@heff1)
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
it 'should not match records that are not less than the given value' do
|
|
465
|
+
@comp.should_not match(@heff2)
|
|
466
|
+
@comp.should_not match(@heff3)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
describe 'LessThanOrEqualToComparison' do
|
|
472
|
+
describe 'with a value matching the property primitive' do
|
|
473
|
+
before :all do
|
|
474
|
+
@comp = Comparison.new(:lte, Heffalump.num_spots, 2)
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
it_should_behave_like 'A valid query condition'
|
|
478
|
+
|
|
479
|
+
it 'should match records that are less than or equal to the given value' do
|
|
480
|
+
@comp.should match(@heff1)
|
|
481
|
+
@comp.should match(@heff2)
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
it 'should not match records that are not less than or equal to the given value' do
|
|
485
|
+
@comp.should_not match(@heff3)
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
describe 'with a value coerced into the property primitive' do
|
|
490
|
+
before :all do
|
|
491
|
+
@comp = Comparison.new(:lte, Heffalump.num_spots, '2')
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it_should_behave_like 'A valid query condition'
|
|
495
|
+
|
|
496
|
+
it 'should match records that are less than or equal to the given value' do
|
|
497
|
+
@comp.should match(@heff1)
|
|
498
|
+
@comp.should match(@heff2)
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
it 'should not match records that are not less than or equal to the given value' do
|
|
502
|
+
@comp.should_not match(@heff3)
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
describe 'RegexpComparison' do
|
|
508
|
+
before :all do
|
|
509
|
+
@comp = Comparison.new(:regexp, Heffalump.color, /green/)
|
|
510
|
+
@heff2.color = 'forest green'
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
it_should_behave_like 'A valid query condition'
|
|
514
|
+
|
|
515
|
+
it 'should match records that match the regexp' do
|
|
516
|
+
@comp.should match(@heff1)
|
|
517
|
+
@comp.should match(@heff2)
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
it "should not match records that don't match the regexp" do
|
|
521
|
+
@comp.should_not match(@heff3)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
end
|