dm-appengine 0.0.5 → 0.0.6
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/Rakefile +3 -5
- data/lib/appengine_adapter.rb +48 -9
- data/lib/dm-appengine/types.rb +73 -6
- data/spec/dm-appengine_spec.rb +83 -1
- data/spec/spec_helper.rb +2 -1
- metadata +5 -25
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'date'
|
|
5
5
|
require 'spec/rake/spectask'
|
6
6
|
|
7
7
|
GEM = "dm-appengine"
|
8
|
-
GEM_VERSION = "0.0.
|
8
|
+
GEM_VERSION = "0.0.6"
|
9
9
|
AUTHOR = "Ryan Brown"
|
10
10
|
EMAIL = "ribrdb@gmail.com"
|
11
11
|
HOMEPAGE = "http://code.google.com/p/appengine-jruby"
|
@@ -23,10 +23,8 @@ spec = Gem::Specification.new do |s|
|
|
23
23
|
s.email = EMAIL
|
24
24
|
s.homepage = HOMEPAGE
|
25
25
|
|
26
|
-
s.add_dependency("appengine-apis", ["~> 0.0.
|
27
|
-
s.add_dependency("dm-core", ["
|
28
|
-
s.add_dependency("addressable")
|
29
|
-
s.add_dependency("extlib")
|
26
|
+
s.add_dependency("appengine-apis", ["~> 0.0.12"])
|
27
|
+
s.add_dependency("dm-core", ["0.10.2"])
|
30
28
|
|
31
29
|
s.require_path = 'lib'
|
32
30
|
s.autorequire = GEM
|
data/lib/appengine_adapter.rb
CHANGED
@@ -150,6 +150,14 @@ module DataMapper
|
|
150
150
|
LessThanComparison => LESS_THAN,
|
151
151
|
LessThanOrEqualToComparison => LESS_THAN_OR_EQUAL,
|
152
152
|
}.freeze
|
153
|
+
|
154
|
+
@@NEGATED_OPERATORS = {
|
155
|
+
EqualToComparison => NOT_EQUAL,
|
156
|
+
GreaterThanComparison => LESS_THAN_OR_EQUAL,
|
157
|
+
GreaterThanOrEqualToComparison => LESS_THAN,
|
158
|
+
LessThanComparison => GREATER_THAN_OR_EQUAL,
|
159
|
+
LessThanOrEqualToComparison => GREATER_THAN,
|
160
|
+
}.freeze
|
153
161
|
|
154
162
|
def initialize(query, kind, adapter)
|
155
163
|
@model = query.model
|
@@ -212,7 +220,13 @@ module DataMapper
|
|
212
220
|
when NullOperation then
|
213
221
|
return
|
214
222
|
when NotOperation then
|
215
|
-
|
223
|
+
if OrOperation === conditions.operand
|
224
|
+
parse_and(conditions.operand)
|
225
|
+
elsif AbstractComparison === conditions.operand
|
226
|
+
parse_comparison(conditions.operand)
|
227
|
+
else
|
228
|
+
raise NotImplementedError, "NOT operator is not supported with #{conditions.operand.class.name}"
|
229
|
+
end
|
216
230
|
when AbstractComparison then
|
217
231
|
parse_comparison(conditions)
|
218
232
|
when OrOperation then
|
@@ -226,7 +240,7 @@ module DataMapper
|
|
226
240
|
|
227
241
|
def parse_key(property, value)
|
228
242
|
unless property.key?
|
229
|
-
raise ArgumentError, "#{property_name(property
|
243
|
+
raise ArgumentError, "#{property_name(property)} is not the key"
|
230
244
|
end
|
231
245
|
case value
|
232
246
|
when Integer, String
|
@@ -234,7 +248,7 @@ module DataMapper
|
|
234
248
|
when Symbol
|
235
249
|
Datastore::Key.from_path(@kind, value.to_s)
|
236
250
|
else
|
237
|
-
raise ArgumentError "Unsupported key value #{value.inspect} (a #{value.class})"
|
251
|
+
raise ArgumentError, "Unsupported key value #{value.inspect} (a #{value.class})"
|
238
252
|
end
|
239
253
|
end
|
240
254
|
|
@@ -276,13 +290,17 @@ module DataMapper
|
|
276
290
|
end
|
277
291
|
|
278
292
|
def parse_comparison(op)
|
279
|
-
if op.
|
280
|
-
return
|
293
|
+
if op.respond_to?(:relationship?) && op.relationship?
|
294
|
+
return parse_conditions(op.foreign_key_mapping)
|
295
|
+
elsif (respond_to?(:foreign_key_conditions) &&
|
296
|
+
op.subject.kind_of?(Associations::Relationship))
|
297
|
+
return parse_conditions(foreign_key_conditions(op))
|
281
298
|
end
|
282
299
|
property = op.subject
|
283
300
|
value = op.value
|
301
|
+
negated = op.negated?
|
284
302
|
if @maybe_get
|
285
|
-
if property.key?
|
303
|
+
if property.key? && !negated
|
286
304
|
case op
|
287
305
|
when EqualToComparison
|
288
306
|
@keys << parse_key(property, value)
|
@@ -298,10 +316,14 @@ module DataMapper
|
|
298
316
|
end
|
299
317
|
end
|
300
318
|
|
301
|
-
if op.kind_of?
|
302
|
-
|
319
|
+
if op.kind_of?(InclusionComparison)
|
320
|
+
parse_inclusion(op)
|
303
321
|
else
|
304
|
-
|
322
|
+
if negated
|
323
|
+
filter_op = @@NEGATED_OPERATORS[op.class]
|
324
|
+
else
|
325
|
+
filter_op = @@OPERATORS[op.class]
|
326
|
+
end
|
305
327
|
if filter_op.nil?
|
306
328
|
raise ArgumentError, "#{op.class} is not a supported comparison"
|
307
329
|
end
|
@@ -311,9 +333,26 @@ module DataMapper
|
|
311
333
|
end
|
312
334
|
end
|
313
335
|
|
336
|
+
def parse_inclusion(op)
|
337
|
+
if Range === op.value
|
338
|
+
parse_range(op)
|
339
|
+
else
|
340
|
+
name = property_name(op.subject)
|
341
|
+
values = op.value.map {|x| property_value(op.subject, x)}
|
342
|
+
if op.negated?
|
343
|
+
values.each do |value|
|
344
|
+
@query.filter(name, NOT_EQUAL, value)
|
345
|
+
end
|
346
|
+
else
|
347
|
+
@query.filter(name, IN, java.util.ArrayList.new(values))
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
314
352
|
def parse_range(op)
|
315
353
|
range = op.value
|
316
354
|
raise NotImplementedError unless range.is_a? Range
|
355
|
+
raise NotImplementedError if op.negated?
|
317
356
|
name = property_name(op.subject)
|
318
357
|
begin_op = GREATER_THAN_OR_EQUAL
|
319
358
|
end_op = if range.exclude_end?
|
data/lib/dm-appengine/types.rb
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
#
|
18
18
|
# Custom types for App Engine
|
19
19
|
|
20
|
-
require 'dm-core/type'
|
20
|
+
require 'dm-core/type' unless defined? DataMapper::Type::PROPERTY_OPTIONS
|
21
21
|
|
22
22
|
module DataMapper
|
23
23
|
module Types
|
@@ -37,17 +37,84 @@ module DataMapper
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
class
|
40
|
+
class AppEngineStringType < Type
|
41
|
+
def self.dump(value, property)
|
42
|
+
self::DATASTORE_TYPE.new(value) if value
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.load(value, property)
|
46
|
+
value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class AppEngineNativeType < Type
|
51
|
+
primitive ::Object
|
52
|
+
|
53
|
+
def self.dump(value, property)
|
54
|
+
value
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.load(value, property)
|
58
|
+
value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Blob < AppEngineStringType
|
41
63
|
primitive String
|
64
|
+
DATASTORE_TYPE = AppEngine::Datastore::Blob
|
42
65
|
size 1024 * 1024
|
43
|
-
|
66
|
+
end
|
67
|
+
|
68
|
+
class ByteString < AppEngineStringType
|
69
|
+
primitive String
|
70
|
+
DATASTORE_TYPE = AppEngine::Datastore::ByteString
|
71
|
+
size 500
|
72
|
+
end
|
73
|
+
|
74
|
+
class Link < AppEngineStringType
|
75
|
+
primitive String
|
76
|
+
DATASTORE_TYPE = AppEngine::Datastore::Link
|
77
|
+
size 2038
|
78
|
+
end
|
79
|
+
|
80
|
+
class Email < AppEngineStringType
|
81
|
+
primitive String
|
82
|
+
DATASTORE_TYPE = AppEngine::Datastore::Email
|
83
|
+
size 500
|
84
|
+
end
|
85
|
+
|
86
|
+
class Category < AppEngineStringType
|
87
|
+
primitive String
|
88
|
+
DATASTORE_TYPE = AppEngine::Datastore::Category
|
89
|
+
size 500
|
90
|
+
end
|
91
|
+
|
92
|
+
class PhoneNumber < AppEngineStringType
|
93
|
+
primitive String
|
94
|
+
DATASTORE_TYPE = AppEngine::Datastore::PhoneNumber
|
95
|
+
size 500
|
96
|
+
end
|
97
|
+
|
98
|
+
class PostalAddress < AppEngineStringType
|
99
|
+
primitive String
|
100
|
+
DATASTORE_TYPE = AppEngine::Datastore::PostalAddress
|
101
|
+
size 500
|
102
|
+
end
|
103
|
+
|
104
|
+
class Rating < Type
|
105
|
+
primitive ::Object
|
106
|
+
|
44
107
|
def self.dump(value, property)
|
45
|
-
AppEngine::Datastore::
|
108
|
+
AppEngine::Datastore::Rating.new(value) if value
|
46
109
|
end
|
47
110
|
|
48
111
|
def self.load(value, property)
|
49
|
-
value
|
112
|
+
value.rating if value
|
50
113
|
end
|
51
114
|
end
|
115
|
+
|
116
|
+
IMHandle = GeoPt = Key = User = AppEngineNativeType
|
117
|
+
|
118
|
+
# TODO store user as email and id?
|
52
119
|
end
|
53
|
-
end
|
120
|
+
end
|
data/spec/dm-appengine_spec.rb
CHANGED
@@ -35,9 +35,18 @@ class TypeTest
|
|
35
35
|
property :bigd, BigDecimal
|
36
36
|
property :flower, Object
|
37
37
|
property :klass, Class
|
38
|
-
$stderr.puts "list: #{List.primitive.ancestors})"
|
39
38
|
property :list, List
|
40
39
|
property :blob, Blob
|
40
|
+
property :bstring, ByteString
|
41
|
+
property :link, Link
|
42
|
+
property :email, Email
|
43
|
+
property :category, Category
|
44
|
+
property :phone, PhoneNumber
|
45
|
+
property :address, PostalAddress
|
46
|
+
property :rating, Rating
|
47
|
+
property :im, IMHandle
|
48
|
+
property :point, GeoPt
|
49
|
+
property :user, User
|
41
50
|
end
|
42
51
|
|
43
52
|
class Flower
|
@@ -180,5 +189,78 @@ describe DataMapper::Adapters::AppEngineAdapter do
|
|
180
189
|
a.reload
|
181
190
|
a.blob.should == '\0'
|
182
191
|
end
|
192
|
+
|
193
|
+
it 'should support ByteString' do
|
194
|
+
a = TypeTest.new(:name => 'bstring', :bstring => '\0')
|
195
|
+
a.save
|
196
|
+
a.reload
|
197
|
+
a.bstring.should == '\0'
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should support Link' do
|
201
|
+
link = "http://example.com/" + "0" * 1000
|
202
|
+
a = TypeTest.new(:name => 'link', :link => link)
|
203
|
+
a.save
|
204
|
+
a.reload
|
205
|
+
a.link.should == link
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should support Email' do
|
209
|
+
a = TypeTest.new(:name => 'email', :email => 'ribrdb@example.com')
|
210
|
+
a.save
|
211
|
+
a.reload
|
212
|
+
a.email.should == 'ribrdb@example.com'
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should support Category' do
|
216
|
+
a = TypeTest.new(:name => 'category', :category => 'tests')
|
217
|
+
a.save
|
218
|
+
a.reload
|
219
|
+
a.category.should == 'tests'
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should support PhoneNumbers" do
|
223
|
+
number = '555-1212'
|
224
|
+
a = TypeTest.new(:name => 'phone', :phone => number)
|
225
|
+
a.save
|
226
|
+
a.reload
|
227
|
+
a.phone.should == number
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should support PostalAddress" do
|
231
|
+
address = '345 Spear St'
|
232
|
+
a = TypeTest.new(:name => 'address', :address => address)
|
233
|
+
a.save
|
234
|
+
a.reload
|
235
|
+
a.address.should == address
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should support Rating" do
|
239
|
+
rating = 34
|
240
|
+
a = TypeTest.new(:name => 'rating', :rating => rating)
|
241
|
+
a.save
|
242
|
+
a.reload
|
243
|
+
a.rating.should == 34
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should support IMHandle" do
|
247
|
+
im = AppEngine::Datastore::IMHandle.new(:xmpp, 'batman@google.com')
|
248
|
+
a = TypeTest.new(:name => 'im', :im => im)
|
249
|
+
a.save
|
250
|
+
a.reload
|
251
|
+
a.im.should == im
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should support GeoPt" do
|
255
|
+
latitude = 32.4
|
256
|
+
longitude = 72.2
|
257
|
+
point = AppEngine::Datastore::GeoPt.new(latitude, longitude)
|
258
|
+
a = TypeTest.new(:name => 'point', :point => point)
|
259
|
+
a.save
|
260
|
+
a.reload
|
261
|
+
a.point.should == point
|
262
|
+
a.point.latitude.should be_close(latitude, 0.1)
|
263
|
+
a.point.longitude.should be_close(longitude, 0.1)
|
264
|
+
end
|
183
265
|
end
|
184
266
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -21,10 +21,11 @@ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
|
21
21
|
require 'rubygems'
|
22
22
|
require 'appengine-sdk'
|
23
23
|
AppEngine::SDK.load_apiproxy
|
24
|
+
AppEngine::SDK.load_labs
|
24
25
|
require 'dm-core'
|
25
26
|
|
26
27
|
ADAPTERS = ['default']
|
27
28
|
PRIMARY = {'default' => "appengine://memory"}
|
28
29
|
|
29
30
|
DataMapper::Logger.new(STDERR, :debug)
|
30
|
-
DataMapper.setup(:default, 'appengine://memory')
|
31
|
+
DataMapper.setup(:default, 'appengine://memory')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-appengine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Brown
|
@@ -9,7 +9,7 @@ autorequire: dm-appengine
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-21 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.
|
23
|
+
version: 0.0.12
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: dm-core
|
@@ -28,29 +28,9 @@ dependencies:
|
|
28
28
|
version_requirement:
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.10.0
|
34
|
-
version:
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: addressable
|
37
|
-
type: :runtime
|
38
|
-
version_requirement:
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: "0"
|
44
|
-
version:
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: extlib
|
47
|
-
type: :runtime
|
48
|
-
version_requirement:
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
31
|
+
- - "="
|
52
32
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
33
|
+
version: 0.10.2
|
54
34
|
version:
|
55
35
|
description: A DataMapper adapter for Google App Engine
|
56
36
|
email: ribrdb@gmail.com
|