dm-ambition 0.10.2
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/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/Manifest.txt +23 -0
- data/README.rdoc +118 -0
- data/Rakefile +35 -0
- data/TODO +0 -0
- data/dm-ambition.gemspec +89 -0
- data/lib/dm-ambition/collection.rb +73 -0
- data/lib/dm-ambition/model.rb +28 -0
- data/lib/dm-ambition/query/filter_processor.rb +361 -0
- data/lib/dm-ambition/query.rb +23 -0
- data/lib/dm-ambition/version.rb +5 -0
- data/lib/dm-ambition.rb +50 -0
- data/spec/public/collection_spec.rb +138 -0
- data/spec/public/model_spec.rb +34 -0
- data/spec/public/shared/filter_shared_spec.rb +221 -0
- data/spec/rcov.opts +6 -0
- data/spec/semipublic/query_spec.rb +718 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +49 -0
- data/tasks/ci.rake +1 -0
- data/tasks/clean.rake +6 -0
- data/tasks/heckle.rake +52 -0
- data/tasks/metrics.rake +37 -0
- data/tasks/spec.rake +41 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +20 -0
- metadata +137 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Ambition
|
3
|
+
module Query
|
4
|
+
@@sexps = {}
|
5
|
+
|
6
|
+
# TODO: spec and document this
|
7
|
+
# @api semipublic
|
8
|
+
def filter(negated = false, &block)
|
9
|
+
# TODO: benchmark Marshal versus just building the sexp on demand
|
10
|
+
|
11
|
+
# deep clone the sexp for multiple re-use
|
12
|
+
sexp = Marshal.load(@@sexps[block.to_s] ||= Marshal.dump(block.to_sexp))
|
13
|
+
|
14
|
+
processor = FilterProcessor.new(block.binding, model, negated)
|
15
|
+
processor.process(sexp)
|
16
|
+
|
17
|
+
merge(:conditions => processor.conditions)
|
18
|
+
end
|
19
|
+
end # module Query
|
20
|
+
end # module Ambition
|
21
|
+
end # module DataMapper
|
22
|
+
|
23
|
+
require Pathname(__FILE__).dirname.expand_path / 'query' / 'filter_processor'
|
data/lib/dm-ambition.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
dir = Pathname(__FILE__).dirname.expand_path + 'dm-ambition'
|
4
|
+
|
5
|
+
require dir / 'collection'
|
6
|
+
require dir / 'model'
|
7
|
+
require dir / 'query'
|
8
|
+
require dir / 'version'
|
9
|
+
|
10
|
+
module DataMapper
|
11
|
+
class Collection
|
12
|
+
include Ambition::Collection
|
13
|
+
end
|
14
|
+
|
15
|
+
module Model
|
16
|
+
include Ambition::Model
|
17
|
+
end
|
18
|
+
|
19
|
+
class Query
|
20
|
+
include Ambition::Query
|
21
|
+
end
|
22
|
+
|
23
|
+
if Gem::Version.new(DataMapper::VERSION) < Gem::Version.new('0.10')
|
24
|
+
module Model
|
25
|
+
def self.descendants
|
26
|
+
Resource.descendants
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Collection
|
31
|
+
def new_collection(query, resources = nil, &block)
|
32
|
+
collection = self.class.new(query, &block)
|
33
|
+
|
34
|
+
if resources
|
35
|
+
collection.replace(resources)
|
36
|
+
end
|
37
|
+
|
38
|
+
collection
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Resource
|
43
|
+
def saved?
|
44
|
+
!new_record?
|
45
|
+
end
|
46
|
+
|
47
|
+
alias new? new_record?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
[ false, true ].each do |loaded|
|
5
|
+
describe DataMapper::Ambition::Collection do
|
6
|
+
cattr_accessor :loaded
|
7
|
+
|
8
|
+
self.loaded = loaded
|
9
|
+
|
10
|
+
before :all do
|
11
|
+
class ::User
|
12
|
+
include DataMapper::Resource
|
13
|
+
|
14
|
+
property :id, Serial
|
15
|
+
property :name, String
|
16
|
+
property :admin, Boolean, :default => false
|
17
|
+
end
|
18
|
+
|
19
|
+
if DataMapper.respond_to?(:auto_migrate!)
|
20
|
+
DataMapper.auto_migrate!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
before :all do
|
25
|
+
@repository = DataMapper.repository(:default)
|
26
|
+
@model = User
|
27
|
+
@query = DataMapper::Query.new(@repository, @model)
|
28
|
+
|
29
|
+
@user = @model.create(:name => 'Dan Kubb', :admin => true)
|
30
|
+
@other = @model.create(:name => 'Sam Smoot')
|
31
|
+
|
32
|
+
@subject = @model.all(@query)
|
33
|
+
@subject.to_a if loaded
|
34
|
+
end
|
35
|
+
|
36
|
+
it_should_behave_like 'it has public filter methods'
|
37
|
+
|
38
|
+
unless loaded || Gem::Version.new(DataMapper::VERSION) < Gem::Version.new('0.10')
|
39
|
+
[ :select, :find_all ].each do |method|
|
40
|
+
describe "##{method}", '(unloaded)' do
|
41
|
+
describe 'when matching resource prepended' do
|
42
|
+
before :all do
|
43
|
+
@subject.unshift(@other)
|
44
|
+
@return = @subject.send(method) { |u| u.admin == true }
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return a Collection' do
|
48
|
+
@return.should be_kind_of(DataMapper::Collection)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should not return self' do
|
52
|
+
@return.should_not equal(@subject)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should not be a kicker' do
|
56
|
+
@return.should_not be_loaded
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return expected values' do
|
60
|
+
@return.should == [ @user ]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'when matching resource appended' do
|
65
|
+
before :all do
|
66
|
+
@subject << @other
|
67
|
+
@return = @subject.send(method) { |u| u.admin == true }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should return a Collection' do
|
71
|
+
@return.should be_kind_of(DataMapper::Collection)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should not return self' do
|
75
|
+
@return.should_not equal(@subject)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should not be a kicker' do
|
79
|
+
@return.should_not be_loaded
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should return expected values' do
|
83
|
+
@return.should == [ @user ]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#reject', '(unloaded)' do
|
90
|
+
describe 'when matching resource prepended' do
|
91
|
+
before :all do
|
92
|
+
@subject.unshift(@other)
|
93
|
+
@return = @subject.reject { |u| u.admin != true }
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should return a Collection' do
|
97
|
+
@return.should be_kind_of(DataMapper::Collection)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should not return self' do
|
101
|
+
@return.should_not equal(@subject)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should not be a kicker' do
|
105
|
+
@return.should_not be_loaded
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should return expected values' do
|
109
|
+
@return.should == [ @user ]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'when matching resource appended' do
|
114
|
+
before :all do
|
115
|
+
@subject << @other
|
116
|
+
@return = @subject.reject { |u| u.admin != true }
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should return a Collection' do
|
120
|
+
@return.should be_kind_of(DataMapper::Collection)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should not return self' do
|
124
|
+
@return.should_not equal(@subject)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should not be a kicker' do
|
128
|
+
@return.should_not be_loaded
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should return expected values' do
|
132
|
+
@return.should == [ @user ]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
describe DataMapper::Ambition::Model do
|
5
|
+
def self.loaded
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
class ::User
|
11
|
+
include DataMapper::Resource
|
12
|
+
|
13
|
+
property :id, Serial
|
14
|
+
property :name, String
|
15
|
+
property :admin, Boolean, :default => false
|
16
|
+
end
|
17
|
+
|
18
|
+
if DataMapper.respond_to?(:auto_migrate!)
|
19
|
+
DataMapper.auto_migrate!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
before :all do
|
24
|
+
@repository = DataMapper.repository(:default)
|
25
|
+
@model = User
|
26
|
+
|
27
|
+
@user = @model.create(:name => 'Dan Kubb', :admin => true)
|
28
|
+
@other = @model.create(:name => 'Sam Smoot')
|
29
|
+
|
30
|
+
@subject = @model
|
31
|
+
end
|
32
|
+
|
33
|
+
it_should_behave_like 'it has public filter methods'
|
34
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
share_examples_for 'it has public filter methods' do
|
2
|
+
[ :select, :find_all ].each do |method|
|
3
|
+
it { @subject.should respond_to(method) }
|
4
|
+
|
5
|
+
describe "##{method}", ('(loaded)' if loaded) do
|
6
|
+
describe 'with simple conditions' do
|
7
|
+
before :all do
|
8
|
+
@return = @subject.send(method) { |u| u.name == 'Dan Kubb' }
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should return a Collection' do
|
12
|
+
@return.should be_kind_of(DataMapper::Collection)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should not return self' do
|
16
|
+
@return.should_not equal(@subject)
|
17
|
+
end
|
18
|
+
|
19
|
+
unless loaded
|
20
|
+
it 'should not be a kicker' do
|
21
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return expected values' do
|
26
|
+
@return.should == [ @user ]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with OR + AND conditions' do
|
31
|
+
before :all do
|
32
|
+
@return = @subject.send(method) { |u| (u.name == 'Dan Kubb' || u.name == 'Sam Smoot') && u.admin == true }
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should return a Collection' do
|
36
|
+
@return.should be_kind_of(DataMapper::Collection)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not return self' do
|
40
|
+
@return.should_not equal(@subject)
|
41
|
+
end
|
42
|
+
|
43
|
+
unless loaded
|
44
|
+
it 'should not be a kicker' do
|
45
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return expected values' do
|
50
|
+
@return.should == [ @user ]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'with AND + OR conditions' do
|
55
|
+
before :all do
|
56
|
+
@return = @subject.send(method) { |u| (u.admin == true && u.name == 'Dan Kubb') || u.name == 'Sam Smoot' }
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return a Collection' do
|
60
|
+
@return.should be_kind_of(DataMapper::Collection)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should not return self' do
|
64
|
+
@return.should_not equal(@subject)
|
65
|
+
end
|
66
|
+
|
67
|
+
unless loaded
|
68
|
+
it 'should not be a kicker' do
|
69
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return expected values' do
|
74
|
+
@return.should == [ @user, @other ]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
[ :detect, :find ].each do |method|
|
81
|
+
it { @subject.should respond_to(method) }
|
82
|
+
|
83
|
+
describe "##{method}", ('(loaded)' if loaded) do
|
84
|
+
describe 'with simple conditions' do
|
85
|
+
before :all do
|
86
|
+
@return = @subject.send(method) { |u| u.name == 'Dan Kubb' }
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should return a Resource' do
|
90
|
+
@return.should be_kind_of(DataMapper::Resource)
|
91
|
+
end
|
92
|
+
|
93
|
+
unless loaded
|
94
|
+
it 'should not be a kicker' do
|
95
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should return expected value' do
|
100
|
+
@return.should == @user
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'with OR + AND conditions' do
|
105
|
+
before :all do
|
106
|
+
@return = @subject.send(method) { |u| (u.name == 'Dan Kubb' || u.name == 'Sam Smoot') && u.admin == true }
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should return a Resource' do
|
110
|
+
@return.should be_kind_of(DataMapper::Resource)
|
111
|
+
end
|
112
|
+
|
113
|
+
unless loaded
|
114
|
+
it 'should not be a kicker' do
|
115
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should return expected value' do
|
120
|
+
@return.should == @user
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'with AND + OR conditions' do
|
125
|
+
before :all do
|
126
|
+
@return = @subject.send(method) { |u| (u.admin == true && u.name == 'Dan Kubb') || u.name == 'Sam Smoot' }
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should return a Resource' do
|
130
|
+
@return.should be_kind_of(DataMapper::Resource)
|
131
|
+
end
|
132
|
+
|
133
|
+
unless loaded
|
134
|
+
it 'should not be a kicker' do
|
135
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should return expected value' do
|
140
|
+
@return.should == @user
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it { @subject.should respond_to(:reject) }
|
147
|
+
|
148
|
+
describe '#reject', ('(loaded)' if loaded) do
|
149
|
+
describe 'with simple conditions' do
|
150
|
+
before :all do
|
151
|
+
@return = @subject.reject { |u| u.name != 'Dan Kubb' }
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should return a Collection' do
|
155
|
+
@return.should be_kind_of(DataMapper::Collection)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should not return self' do
|
159
|
+
@return.should_not equal(@subject)
|
160
|
+
end
|
161
|
+
|
162
|
+
unless loaded
|
163
|
+
it 'should not be a kicker' do
|
164
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'should return expected values' do
|
169
|
+
@return.should == [ @user ]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe 'with OR + AND conditions' do
|
174
|
+
before :all do
|
175
|
+
@return = @subject.reject { |u| (u.name == 'Dan Kubb' || u.name == 'Sam Smoot') && u.admin == true }
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should return a Collection' do
|
179
|
+
@return.should be_kind_of(DataMapper::Collection)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should not return self' do
|
183
|
+
@return.should_not equal(@subject)
|
184
|
+
end
|
185
|
+
|
186
|
+
unless loaded
|
187
|
+
it 'should not be a kicker' do
|
188
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should return expected values' do
|
193
|
+
@return.should == [ @other ]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe 'with AND + OR conditions' do
|
198
|
+
before :all do
|
199
|
+
@return = @subject.reject { |u| (u.admin == true && u.name == 'Dan Kubb') || u.name == 'Sam Smoot' }
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'should return a Collection' do
|
203
|
+
@return.should be_kind_of(DataMapper::Collection)
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should not return self' do
|
207
|
+
@return.should_not equal(@subject)
|
208
|
+
end
|
209
|
+
|
210
|
+
unless loaded
|
211
|
+
it 'should not be a kicker' do
|
212
|
+
@subject.respond_to?(:loaded) and @subject.should_not be_loaded
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'should return expected values' do
|
217
|
+
@return.should == []
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|