dm-parse 0.1.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/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +63 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/lib/adapters/parse_adapter.rb +238 -0
- data/lib/collection.rb +8 -0
- data/lib/dm-parse.rb +12 -0
- data/lib/is/parse.rb +36 -0
- data/lib/parse/query.rb +117 -0
- data/lib/parse/resource.rb +19 -0
- data/lib/property/parse_date.rb +17 -0
- data/lib/property/parse_key.rb +26 -0
- data/lib/property/parse_pointer.rb +21 -0
- data/spec/integration_spec.rb +98 -0
- data/spec/parse_adapter_spec.rb +302 -0
- data/spec/parse_date_spec.rb +45 -0
- data/spec/parse_key_spec.rb +32 -0
- data/spec/parse_pointer_spec.rb +32 -0
- data/spec/query_spec.rb +25 -0
- data/spec/resource_spec.rb +5 -0
- data/spec/spec_helper.rb +58 -0
- metadata +315 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "resource" do
|
4
|
+
subject { resource }
|
5
|
+
|
6
|
+
let(:resource) { model.new title: "Test Title", rank: 3, body: "Test Body" }
|
7
|
+
let(:model) { Article }
|
8
|
+
|
9
|
+
before { model.all.destroy }
|
10
|
+
|
11
|
+
it { should be_new }
|
12
|
+
it { should be_dirty }
|
13
|
+
its(:id) { should be_nil }
|
14
|
+
its(:created_at) { should be_nil }
|
15
|
+
its(:updated_at) { should be_nil }
|
16
|
+
|
17
|
+
context "after save" do
|
18
|
+
before { resource.save }
|
19
|
+
|
20
|
+
it { should_not be_nil }
|
21
|
+
it { should_not be_dirty }
|
22
|
+
its(:id) { should_not be_nil }
|
23
|
+
its(:created_at) { should_not be_nil }
|
24
|
+
its(:updated_at) { should_not be_nil }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "collection" do
|
29
|
+
subject { collection }
|
30
|
+
|
31
|
+
let(:model) { Article }
|
32
|
+
let(:collection) { model.all(:rank.gte => 5, :closed_at.gt => 1.day.from_now, :closed_at.lt => 3.days.from_now, :comments => { :body => /aa/im }) }
|
33
|
+
|
34
|
+
before { model.all.destroy }
|
35
|
+
before { Comment.all.destroy }
|
36
|
+
|
37
|
+
its(:size) { should eq(0) }
|
38
|
+
|
39
|
+
context "when resource in scope is saved" do
|
40
|
+
before do
|
41
|
+
resource = model.create! rank: 5, closed_at: 2.day.from_now
|
42
|
+
resource.comments.create body: "AA"
|
43
|
+
end
|
44
|
+
|
45
|
+
its(:size) { should eq(1) }
|
46
|
+
its(:count) { should eq(1) }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when resource out of scope is saved" do
|
50
|
+
before { model.create rank: 4 }
|
51
|
+
|
52
|
+
its(:size) { should eq(0) }
|
53
|
+
its(:count) { should eq(0) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe User do
|
58
|
+
subject { user }
|
59
|
+
|
60
|
+
before do
|
61
|
+
repository :master do
|
62
|
+
model.all.destroy
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:model) { described_class }
|
67
|
+
let(:username) { "testuser0" }
|
68
|
+
let(:password) { "abcdefgh" }
|
69
|
+
let(:user) { model.new username: username, password: password }
|
70
|
+
|
71
|
+
it { should be_valid }
|
72
|
+
|
73
|
+
context "when a vaid email is given" do
|
74
|
+
let(:user) { model.new username: username, password: password, email: "#{username}@abc.com" }
|
75
|
+
|
76
|
+
it { should be_valid }
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when an invalid email is given" do
|
80
|
+
let(:user) { model.new username: username, password: password, email: "dafdjlfdsaj" }
|
81
|
+
|
82
|
+
it { should_not be_valid }
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "class" do
|
86
|
+
subject { model }
|
87
|
+
|
88
|
+
let(:user) { model.create! username: username, password: password }
|
89
|
+
|
90
|
+
its(:storage_name) { should eq("_User") }
|
91
|
+
|
92
|
+
describe "#authenticate" do
|
93
|
+
subject { model.authenticate username, password }
|
94
|
+
|
95
|
+
it { should eq(user) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DataMapper::Adapters::ParseAdapter do
|
4
|
+
let(:adapter) { DataMapper.setup(:default, options) }
|
5
|
+
let(:options) { { adapter: :parse, app_id: app_id, api_key: api_key } }
|
6
|
+
let(:app_id) { "xxx" }
|
7
|
+
let(:api_key) { "yyy" }
|
8
|
+
let(:app_id_header) { "X-Parse-Application-Id" }
|
9
|
+
let(:api_key_header) { "X-Parse-REST-API-Key" }
|
10
|
+
let(:master_key_header) { "X-Parse-Master-Key" }
|
11
|
+
let(:model) { Article }
|
12
|
+
|
13
|
+
describe "#parse_conditions_for" do
|
14
|
+
subject { adapter.send :parse_conditions_for, query }
|
15
|
+
|
16
|
+
context "when query is nil" do
|
17
|
+
let(:query) { model.all.query }
|
18
|
+
it { should be_nil }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when query assigns some exact values" do
|
22
|
+
let(:query) { model.all(:id => "z", :title => "x", :body => "y").query }
|
23
|
+
it { should eq("objectId" => "z", "title" => "x", "body" => "y") }
|
24
|
+
end
|
25
|
+
|
26
|
+
[:gt, :gte, :lt, :lte].each do |slug|
|
27
|
+
context "when query has #{slug} comparison" do
|
28
|
+
let(:query) { model.all(:id => "z", :rank.send(slug) => 5).query }
|
29
|
+
it { should eq("objectId" => "z", "rank" => {"$#{slug}" => 5}) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when query has :not operation" do
|
34
|
+
let(:query) { model.all(:rank.not => 5, :body.not => "x").query }
|
35
|
+
it { should eq("rank" => {"$ne" => 5}, "body" => {"$ne" => "x"}) }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when query has multiple comparisons of one field" do
|
39
|
+
let(:query) { model.all(:rank.lt => 5, :rank.gt => 3).query }
|
40
|
+
it { should eq("rank" => {"$lt" => 5, "$gt" => 3}) }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when query has :in comparison" do
|
44
|
+
let(:query) { model.all("rank" => 1..3).query }
|
45
|
+
it { should eq("rank" => {"$in" => (1..3).to_a}) }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when query has :regexp comparison" do
|
49
|
+
let(:query) { model.all(:body => regex).query }
|
50
|
+
let(:regex) { /^[A-Z]\d/ }
|
51
|
+
|
52
|
+
it { should eq("body" => {"$regex" => "^[A-Z]\\d"}) }
|
53
|
+
|
54
|
+
context "when regular expersion has options" do
|
55
|
+
let(:regex) { /bbq/mi }
|
56
|
+
|
57
|
+
it { should eq("body" => {"$regex"=>"bbq", "$options"=>"im"}) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when query has :or operation" do
|
62
|
+
let(:query) { (model.all(:rank => 3) + model.all(:rank => 4) + model.all(:rank => 5)).query }
|
63
|
+
it { should eq("$or" => [{"rank" => 3}, {"rank" => 4}, {"rank" => 5}]) }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when query has union operator" do
|
67
|
+
let(:query) { (model.all(:rank => 3) | model.all(:rank => 4) | model.all(:rank => 5)).query }
|
68
|
+
it { should eq("$or" => [{"rank" => 3}, {"rank" => 4}, {"rank" => 5}]) }
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when query has and operator" do
|
72
|
+
let(:query) { (model.all("rank" => 5) & model.all("body" => "x")).query }
|
73
|
+
it { should eq("rank" => 5, "body" => "x") }
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when query has complex :not operation" do
|
77
|
+
let(:query) { (model.all - model.all(:rank => 5, :body => "x")).query }
|
78
|
+
it { should eq("rank" => {"$ne" => 5}, "body" => {"$ne" => "x"}) }
|
79
|
+
|
80
|
+
context "when condition is not EqualToComparison" do
|
81
|
+
let(:query) { model.all(:rank.not => [2, 3]).query }
|
82
|
+
it { should eq("rank" => {"$nin" => [2, 3]}) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "exceptions" do
|
87
|
+
subject { -> { adapter.send :parse_conditions_for, query } }
|
88
|
+
|
89
|
+
context "when the key is same" do
|
90
|
+
let(:query) { (model.all("rank" => 5) & model.all("rank" => 3)).query }
|
91
|
+
it { should raise_error("can only use one EqualToComparison for a field") }
|
92
|
+
end
|
93
|
+
|
94
|
+
context "when query has :eql and others of one field" do
|
95
|
+
let(:query) { model.all(:rank => 5, :rank.gt => 3).query }
|
96
|
+
it { should raise_error }
|
97
|
+
end
|
98
|
+
end # exceptions
|
99
|
+
end # #parse_conditions_for
|
100
|
+
|
101
|
+
describe "#parse_orders_for" do
|
102
|
+
subject { adapter.send :parse_orders_for, query }
|
103
|
+
let(:query) { model.all("body" => "x").query }
|
104
|
+
it { should be_nil }
|
105
|
+
|
106
|
+
context "when orders are given" do
|
107
|
+
let(:query) { model.all(:order => [:rank.asc, :title.desc]).query }
|
108
|
+
it { should eq("rank,-title") }
|
109
|
+
end
|
110
|
+
end # #parse_orders_for
|
111
|
+
|
112
|
+
describe "#parse_limit_for" do
|
113
|
+
subject { adapter.send :parse_limit_for, query }
|
114
|
+
let(:query) { model.all.query }
|
115
|
+
it { should eq(1000) }
|
116
|
+
|
117
|
+
context "when 0 is given" do
|
118
|
+
let(:query) { model.all(:limit => 0).query }
|
119
|
+
it { should eq(0) }
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "exceptions" do
|
123
|
+
subject { -> { adapter.send :parse_limit_for, query } }
|
124
|
+
|
125
|
+
context "when 1001 is given" do
|
126
|
+
let(:query) { model.all(:limit => 1001).query }
|
127
|
+
it { should raise_error("Parse limit: only number from 0 to 1000 is valid") }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end # #parse_limit_for
|
131
|
+
|
132
|
+
describe "#parse_offset_for" do
|
133
|
+
subject { adapter.send :parse_offset_for, query }
|
134
|
+
let(:query) { model.all.query }
|
135
|
+
it { should eq(0) }
|
136
|
+
|
137
|
+
context "when a number is given" do
|
138
|
+
let(:query) { model.all(:offset => number, :limit => 200).query }
|
139
|
+
|
140
|
+
context "the number is positive" do
|
141
|
+
let(:number) { 1 }
|
142
|
+
it { should eq(number) }
|
143
|
+
end
|
144
|
+
|
145
|
+
context "the number is positive" do
|
146
|
+
let(:number) { 0 }
|
147
|
+
it { should eq(number) }
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "exceptions" do
|
152
|
+
subject { -> { adapter.send :parse_offset_for, query } }
|
153
|
+
let(:query) { model.all(:offset => number, :limit => 200).query }
|
154
|
+
|
155
|
+
context "the number is negative" do
|
156
|
+
let(:number) { -1 }
|
157
|
+
it { should raise_error }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end # #parse_offset_for
|
161
|
+
|
162
|
+
describe "#parse_params_for" do
|
163
|
+
subject { adapter.send :parse_params_for, query }
|
164
|
+
let(:query) { model.all.query }
|
165
|
+
it { should eq(:limit => 1000) }
|
166
|
+
|
167
|
+
context "when limit is given" do
|
168
|
+
let(:query) { model.all(:limit => 200).query }
|
169
|
+
it { should eq(:limit => 200) }
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when conditions is given" do
|
173
|
+
let(:query) { model.all(:rank => 5).query }
|
174
|
+
it { should eq(:limit => 1000, :where => {"rank" => 5}.to_json) }
|
175
|
+
end
|
176
|
+
|
177
|
+
context "when offset is given" do
|
178
|
+
let(:query) { model.all(:limit => 200, :offset => 300).query }
|
179
|
+
it { should eq(:limit => 200, :skip => 300) }
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when orders are given" do
|
183
|
+
let(:query) { model.all(:order => [:rank.desc]).query }
|
184
|
+
it { should eq(:limit => 1000, :order => "-rank") }
|
185
|
+
end
|
186
|
+
end # #parse_params_for
|
187
|
+
|
188
|
+
shared_examples_for DataMapper::Parse::Resource do
|
189
|
+
let(:options) { { adapter: :parse, app_id: app_id, api_key: api_key} }
|
190
|
+
|
191
|
+
it { should be_a(DataMapper::Parse::Resource) }
|
192
|
+
its(:options) { should eq(format: :json, headers: {app_id_header => app_id, api_key_header => api_key}) }
|
193
|
+
context "when master mode is on" do
|
194
|
+
let(:options) { { adapter: :parse, app_id: app_id, api_key: api_key, master: true } }
|
195
|
+
|
196
|
+
its(:options) { should eq(format: :json, headers: {app_id_header => app_id, master_key_header => api_key}) }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#classes" do
|
201
|
+
subject { adapter.classes }
|
202
|
+
its(:url) { should eq("https://api.parse.com/1/classes") }
|
203
|
+
it_should_behave_like DataMapper::Parse::Resource
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#users" do
|
207
|
+
subject { adapter.users }
|
208
|
+
its(:url) { should eq("https://api.parse.com/1/users") }
|
209
|
+
it_should_behave_like DataMapper::Parse::Resource
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "#login" do
|
213
|
+
subject { adapter.login }
|
214
|
+
its(:url) { should eq("https://api.parse.com/1/login") }
|
215
|
+
it_should_behave_like DataMapper::Parse::Resource
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "#password_reset" do
|
219
|
+
subject { adapter.password_reset }
|
220
|
+
its(:url) { should eq("https://api.parse.com/1/requestPasswordReset") }
|
221
|
+
it_should_behave_like DataMapper::Parse::Resource
|
222
|
+
end
|
223
|
+
|
224
|
+
describe "#parse_resources_for" do
|
225
|
+
subject { adapter.parse_resources_for model }
|
226
|
+
it { should eq(adapter.classes[model.storage_name]) }
|
227
|
+
|
228
|
+
context "when storage_name of model is _User" do
|
229
|
+
before(:each) { model.stub(storage_name: "_User") }
|
230
|
+
it { should eq(adapter.users) }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "#parse_resource_for" do
|
235
|
+
subject { adapter.parse_resource_for resource }
|
236
|
+
let(:resource) { model.new id: "xxx" }
|
237
|
+
it { should eq(adapter.parse_resources_for(model)["xxx"]) }
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "#create" do
|
241
|
+
subject { adapter.create resources }
|
242
|
+
|
243
|
+
let(:resources) { [resource] }
|
244
|
+
let(:resource) { model.new attributes }
|
245
|
+
let(:attributes) { { id: "fd", rank: 3, created_at: 1.day.ago, updated_at: 2.days.ago } }
|
246
|
+
|
247
|
+
before(:each) do
|
248
|
+
double_resources = double("resource")
|
249
|
+
double_resources.should_receive(:post).with(params: {"rank" => 3}).once.and_return({"createdAt" => "2011-08-20T02:06:57.931Z", "objectId" => "Ed1nuqPvcm"})
|
250
|
+
adapter.stub(parse_resources_for: double_resources)
|
251
|
+
end
|
252
|
+
|
253
|
+
it { should eq(1) }
|
254
|
+
end
|
255
|
+
|
256
|
+
describe "#read" do
|
257
|
+
subject { adapter.read query }
|
258
|
+
|
259
|
+
let(:query) { model.all(:rank => 4).query }
|
260
|
+
let(:results) { [{"objectId" => "anything"}] }
|
261
|
+
|
262
|
+
before(:each) do
|
263
|
+
double_resources = double("resource")
|
264
|
+
double_resources.should_receive(:get).with(params: { limit: 1000, where: {"rank" => 4}.to_json }).once.and_return("results" => results)
|
265
|
+
adapter.stub(parse_resources_for: double_resources)
|
266
|
+
end
|
267
|
+
|
268
|
+
it { should eq(results) }
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "#delete" do
|
272
|
+
subject { adapter.delete resources }
|
273
|
+
|
274
|
+
let(:resources) { [resource] }
|
275
|
+
let(:resource) { model.new id: id }
|
276
|
+
let(:id) { "xxx" }
|
277
|
+
|
278
|
+
before(:each) do
|
279
|
+
double_resource = double("resource")
|
280
|
+
double_resource.should_receive(:delete).with(no_args).once.and_return({})
|
281
|
+
adapter.stub(parse_resource_for: double_resource)
|
282
|
+
end
|
283
|
+
|
284
|
+
it { should eq(1) }
|
285
|
+
end
|
286
|
+
|
287
|
+
describe "#update" do
|
288
|
+
subject { adapter.update attributes, resources }
|
289
|
+
|
290
|
+
let(:resources) { [resource] }
|
291
|
+
let(:resource) { model.new id: "xxx" }
|
292
|
+
let(:attributes) { model.new(rank: 5, created_at: 1.day.ago, updated_at: 2.days.ago).attributes(:property) }
|
293
|
+
|
294
|
+
before(:each) do
|
295
|
+
double_resource = double("resource")
|
296
|
+
double_resource.should_receive(:put).with(params: {"rank" => 5}).once.and_return("updatedAt" => "2011-08-21T18:02:52.248Z")
|
297
|
+
adapter.stub(parse_resource_for: double_resource)
|
298
|
+
end
|
299
|
+
|
300
|
+
it { should eq(1) }
|
301
|
+
end
|
302
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DataMapper::Property::ParseDate do
|
4
|
+
subject { property }
|
5
|
+
let(:property) { Article.properties[:created_at] }
|
6
|
+
let(:datetime) { DateTime.parse("2011-08-21T18:02:52.249Z") }
|
7
|
+
|
8
|
+
describe "#dump" do
|
9
|
+
subject { property.dump value }
|
10
|
+
let(:value) { datetime }
|
11
|
+
|
12
|
+
it { should eq("__type" => "Date", "iso" => datetime.utc.iso8601(3)) }
|
13
|
+
|
14
|
+
context "when value is nil" do
|
15
|
+
let(:value) { nil }
|
16
|
+
|
17
|
+
it { should be_nil }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#load" do
|
22
|
+
subject { property.load value }
|
23
|
+
let(:value) { {"__type" => "Date", "iso" => datetime.utc.iso8601(3)} }
|
24
|
+
|
25
|
+
it { should eq(datetime) }
|
26
|
+
|
27
|
+
context "when value is in string" do
|
28
|
+
let(:value) { "2011-08-21T18:02:52.249Z" }
|
29
|
+
|
30
|
+
it { should eq(datetime) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when value is nil" do
|
34
|
+
let(:value) { nil }
|
35
|
+
|
36
|
+
it { should be_nil }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#valid?" do
|
41
|
+
subject { property.valid? datetime }
|
42
|
+
|
43
|
+
it { should be_true }
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DataMapper::Property::ParseKey do
|
4
|
+
subject { property }
|
5
|
+
let(:property) { Article.properties[:id] }
|
6
|
+
|
7
|
+
describe "#dump" do
|
8
|
+
subject { property.dump value }
|
9
|
+
let(:value) { "xxx" }
|
10
|
+
|
11
|
+
it { should eq("xxx") }
|
12
|
+
|
13
|
+
context "when value is nil" do
|
14
|
+
let(:value) { nil }
|
15
|
+
|
16
|
+
it { should be_nil }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#load" do
|
21
|
+
subject { property.load value }
|
22
|
+
let(:value) { "xxx" }
|
23
|
+
|
24
|
+
it { should eq("xxx") }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#valid?" do
|
28
|
+
subject { property.valid? "xxx" }
|
29
|
+
|
30
|
+
it { should be_true }
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DataMapper::Property::ParsePointer do
|
4
|
+
subject { property }
|
5
|
+
let(:property) { Comment.properties[:article_id] }
|
6
|
+
|
7
|
+
describe "#dump" do
|
8
|
+
subject { property.dump value }
|
9
|
+
let(:value) { "xxx" }
|
10
|
+
|
11
|
+
it { should eq("__type" => "Pointer", "className" => Article.storage_name, "objectId" => "xxx") }
|
12
|
+
|
13
|
+
context "when value is nil" do
|
14
|
+
let(:value) { nil }
|
15
|
+
|
16
|
+
it { should be_nil }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#load" do
|
21
|
+
subject { property.load value }
|
22
|
+
let(:value) { {"__type" => "Pointer", "className" => Article.storage_name, "objectId" => "xxx"} }
|
23
|
+
|
24
|
+
it { should eq("xxx") }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#valid?" do
|
28
|
+
subject { property.valid? "xxx" }
|
29
|
+
|
30
|
+
it { should be_true }
|
31
|
+
end
|
32
|
+
end
|
data/spec/query_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DataMapper::Parse::Conditions::Regex do
|
4
|
+
let(:regex) { described_class.new value }
|
5
|
+
|
6
|
+
describe "#options" do
|
7
|
+
subject { regex.options }
|
8
|
+
|
9
|
+
context "when case insensitive option is on" do
|
10
|
+
let(:value) { /bbq/i }
|
11
|
+
it { should eq("i") }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when multiline option is on" do
|
15
|
+
let(:value) { /bbq/m }
|
16
|
+
it { should eq("m") }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when both case insensitive and multiline option is on" do
|
20
|
+
let(:value) { /bbq/mi }
|
21
|
+
it { should eq("im") }
|
22
|
+
end
|
23
|
+
end # #regex_options
|
24
|
+
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'dm-parse'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
# To run the tests, setup a Parse environment in "parse_env.yml"
|
15
|
+
# under the same directory, which I don't provide.
|
16
|
+
env_file = File.join(File.dirname(__FILE__), "parse_env.yml")
|
17
|
+
settings = YAML::load(File.read env_file)
|
18
|
+
app_id = settings["app_id"]
|
19
|
+
api_key = settings["api_key"]
|
20
|
+
master_key = settings["master_key"]
|
21
|
+
|
22
|
+
raise "You must setup a parse environment before testing" unless app_id && api_key && master_key
|
23
|
+
|
24
|
+
DataMapper.setup :default, adapter: :parse, app_id: app_id, api_key: api_key
|
25
|
+
DataMapper.setup :master, adapter: :parse, app_id: app_id, api_key: master_key, master: true
|
26
|
+
|
27
|
+
class User
|
28
|
+
include DataMapper::Resource
|
29
|
+
|
30
|
+
is :parse_user
|
31
|
+
storage_names[:master] = "_User"
|
32
|
+
end
|
33
|
+
|
34
|
+
class Article
|
35
|
+
include DataMapper::Resource
|
36
|
+
|
37
|
+
is :parse
|
38
|
+
|
39
|
+
property :title, String
|
40
|
+
property :body, Text
|
41
|
+
property :rank, Integer
|
42
|
+
property :closed_at, ParseDate
|
43
|
+
|
44
|
+
has n, :comments
|
45
|
+
end
|
46
|
+
|
47
|
+
class Comment
|
48
|
+
include DataMapper::Resource
|
49
|
+
|
50
|
+
is :parse
|
51
|
+
|
52
|
+
property :body, Text
|
53
|
+
|
54
|
+
belongs_to :article
|
55
|
+
end
|
56
|
+
|
57
|
+
DataMapper.finalize
|
58
|
+
|