dm-appengine 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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.5"
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.3"])
27
- s.add_dependency("dm-core", ["~> 0.10.0"])
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
@@ -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
- raise NotImplementedError, "NOT operator is not supported"
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, true)} is not the key"
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.subject.kind_of?(Associations::Relationship)
280
- return foreign_key_conditions(op)
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? InclusionComparison
302
- parse_range(op)
319
+ if op.kind_of?(InclusionComparison)
320
+ parse_inclusion(op)
303
321
  else
304
- filter_op = @@OPERATORS[op.class]
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?
@@ -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 Blob < Type
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::Blob.new(value) if value
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
@@ -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.5
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-10-05 00:00:00 -07:00
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.3
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: "0"
33
+ version: 0.10.2
54
34
  version:
55
35
  description: A DataMapper adapter for Google App Engine
56
36
  email: ribrdb@gmail.com