dm-persevere-adapter 0.47.1 → 0.48.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/model_json_support.rb +21 -7
- data/lib/persevere_adapter.rb +21 -10
- data/lib/types/json_reference.rb +65 -0
- data/lib/types/json_reference_collection.rb +92 -0
- data/spec/persevere_adapter_spec.rb +82 -2
- data/spec/persevere_spec.rb +1 -1
- metadata +28 -13
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.48.0
|
data/lib/model_json_support.rb
CHANGED
@@ -23,13 +23,27 @@ module DataMapper
|
|
23
23
|
class Property
|
24
24
|
def to_json_schema_hash(repo)
|
25
25
|
tm = repository(repo).adapter.type_map
|
26
|
-
json_hash = {
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
json_hash = {}
|
27
|
+
|
28
|
+
if type.eql?(DataMapper::Types::JsonReference)
|
29
|
+
json_hash = { "type" => {"$ref" => "../#{@reference_class.storage_name}"}, "optional" => true }
|
30
|
+
elsif type.eql?(DataMapper::Types::JsonReferenceCollection)
|
31
|
+
json_hash = { "type" => "array",
|
32
|
+
"optional" => true,
|
33
|
+
"items" => {"$ref" => "../#{@reference_class.storage_name}"}
|
34
|
+
}
|
35
|
+
# "maxItems" => # For 0..3
|
36
|
+
# "minItems" =>
|
37
|
+
else
|
38
|
+
json_hash = { "type" => tm[type][:primitive] }
|
39
|
+
json_hash.merge!( tm[type].reject{ |key,value| key == :primitive } )
|
40
|
+
json_hash.merge!({ "optional" => true }) unless required?
|
41
|
+
json_hash.merge!({ "unique" => true}) if unique?
|
42
|
+
json_hash.merge!({"position" => @position }) unless @position.nil?
|
43
|
+
json_hash.merge!({"prefix" => @prefix }) unless @prefix.nil?
|
44
|
+
json_hash.merge!({"separator" => @separator }) unless @separator.nil?
|
45
|
+
end
|
46
|
+
|
33
47
|
# MIN
|
34
48
|
# MAX
|
35
49
|
json_hash
|
data/lib/persevere_adapter.rb
CHANGED
@@ -9,6 +9,9 @@ require 'bigdecimal'
|
|
9
9
|
require 'model_json_support'
|
10
10
|
require 'persevere'
|
11
11
|
|
12
|
+
require 'types/json_reference'
|
13
|
+
require 'types/json_reference_collection'
|
14
|
+
|
12
15
|
class BigDecimal
|
13
16
|
alias to_json_old to_json
|
14
17
|
|
@@ -600,17 +603,25 @@ module DataMapper
|
|
600
603
|
def make_json_compatible_hash(resource)
|
601
604
|
json_rsrc = Hash.new
|
602
605
|
resource.attributes(:property).each do |property, value|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
606
|
+
|
607
|
+
next if value.nil? || (value.is_a?(Array) && value.empty?)
|
608
|
+
|
609
|
+
if property.type == DataMapper::Types::JsonReference ||
|
610
|
+
property.type == DataMapper::Types::JsonReferenceCollection
|
611
|
+
json_rsrc[property.field] = property.value(value)
|
612
|
+
else
|
613
|
+
json_rsrc[property.field] = case value
|
614
|
+
when DateTime then value.new_offset(0).strftime("%Y-%m-%dT%H:%M:%SZ")
|
615
|
+
when Date then value.to_s
|
616
|
+
when Time then value.strftime("%H:%M:%S")
|
617
|
+
when Float then value.to_f
|
618
|
+
when BigDecimal then value.to_f
|
619
|
+
when Integer then value.to_i
|
620
|
+
else resource[property.name]
|
621
|
+
end
|
612
622
|
end
|
613
|
-
end
|
623
|
+
end
|
624
|
+
|
614
625
|
json_rsrc
|
615
626
|
end
|
616
627
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Types
|
3
|
+
class JsonReference < Type
|
4
|
+
primitive String
|
5
|
+
length 50
|
6
|
+
lazy true
|
7
|
+
|
8
|
+
# Return the Ruby hash (to be turned into JSON) for insertion into the database
|
9
|
+
# @api semipublic
|
10
|
+
def self.dump(value, property)
|
11
|
+
value.save! unless value.saved?
|
12
|
+
return nil if value.nil?
|
13
|
+
ref_path = "../#{property.reference_class.storage_name}/#{value[:id]}"
|
14
|
+
result = { "$ref" => ref_path }
|
15
|
+
|
16
|
+
return result
|
17
|
+
end
|
18
|
+
|
19
|
+
# @api semipublic
|
20
|
+
def self.load(value, property)
|
21
|
+
return value if value.class.eql?(property.reference_class)
|
22
|
+
return nil if value.nil?
|
23
|
+
|
24
|
+
id = value.has_key?("$ref") ? value["$ref"] : value["id"]
|
25
|
+
id = id.split("/")[-1]
|
26
|
+
property.reference_class.get(id)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Should return the public value we are looking for.
|
30
|
+
# @api semipublic
|
31
|
+
def self.typecast(value, property)
|
32
|
+
return value if value.class.eql?(property.reference_class)
|
33
|
+
return nil if value.nil?
|
34
|
+
|
35
|
+
id = value.has_key?("$ref") ? value["$ref"] : value["id"]
|
36
|
+
id = id.split("/")[-1]
|
37
|
+
property.reference_class.get(id)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def self.bind(property)
|
42
|
+
property.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
|
43
|
+
def primitive?(value)
|
44
|
+
puts "This is my primitive!"
|
45
|
+
|
46
|
+
value.kind_of?(Array)
|
47
|
+
end
|
48
|
+
RUBY
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Property
|
55
|
+
attr_accessor :reference_class
|
56
|
+
|
57
|
+
alias initialize_without_reference_class initialize
|
58
|
+
def initialize_with_reference_class(model, name, type, options = {})
|
59
|
+
@reference_class = options.delete(:reference)
|
60
|
+
|
61
|
+
initialize_without_reference_class(model, name, type, options)
|
62
|
+
end
|
63
|
+
alias initialize initialize_with_reference_class
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'ruby-debug'
|
2
|
+
module DataMapper
|
3
|
+
module Types
|
4
|
+
class JsonReferenceCollection < Type
|
5
|
+
primitive String
|
6
|
+
length 5000
|
7
|
+
lazy true
|
8
|
+
|
9
|
+
def self.dump(value, property)
|
10
|
+
return nil unless value.class.eql?(Array) || value.blank?
|
11
|
+
value.map{|v| v.save! unless v.saved? }
|
12
|
+
results = value.map{|v| { "$ref" => "../#{property.reference_class.storage_name}/#{v[:id]}" }}
|
13
|
+
|
14
|
+
return results
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.load(value, property)
|
18
|
+
return [] if value.nil?
|
19
|
+
|
20
|
+
value.map do |v|
|
21
|
+
if v.class.eql?(property.reference_class)
|
22
|
+
v
|
23
|
+
elsif v.class.eql?(Hash)
|
24
|
+
id = v.has_key?("$ref") ? v["$ref"] : v["id"]
|
25
|
+
id = id.split("/")[-1]
|
26
|
+
property.reference_class.get(id)
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Should return the public value we are looking for.
|
34
|
+
def self.typecast(value, property)
|
35
|
+
return [] if value.nil?
|
36
|
+
|
37
|
+
value.map do |v|
|
38
|
+
if v.class.eql?(property.reference_class)
|
39
|
+
v
|
40
|
+
elsif v.class.eql?(Hash)
|
41
|
+
id = v.has_key?("$ref") ? v["$ref"] : v["id"]
|
42
|
+
id = id.split("/")[-1]
|
43
|
+
property.reference_class.get(id)
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
def self.bind(property)
|
52
|
+
model = property.model
|
53
|
+
name = property.name.to_s
|
54
|
+
instance_variable_name = property.instance_variable_name
|
55
|
+
|
56
|
+
property.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
|
57
|
+
# Primitive error checking. Get it?
|
58
|
+
def primitive?(value)
|
59
|
+
value.kind_of?(Array)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
RUBY
|
64
|
+
|
65
|
+
# This is hack`n slash that should be reworked.
|
66
|
+
model.class_eval <<-RUBY, __FILE__, __LINE__ +1
|
67
|
+
def #{name}
|
68
|
+
original_attributes[properties[#{name.inspect}]] = []
|
69
|
+
return #{instance_variable_name} if defined?(#{instance_variable_name})
|
70
|
+
#{instance_variable_name} = properties[#{name.inspect}].get(self)
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
|
74
|
+
model.send(:resource_methods).add(name)
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Setup in json_reference.rb
|
82
|
+
# class Property
|
83
|
+
# attr_accessor :reference_class
|
84
|
+
#
|
85
|
+
# alias original_initialize initialize
|
86
|
+
# def initialize(model, name, type, options = {})
|
87
|
+
# @reference_class = options.delete(:reference)
|
88
|
+
#
|
89
|
+
# original_initialize(model, name, type, options)
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
end
|
@@ -89,7 +89,7 @@ describe DataMapper::Adapters::PersevereAdapter do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
after :all do
|
92
|
-
|
92
|
+
DataMapper::Model.descendants.each{|cur_model| cur_model.auto_migrate_down! }
|
93
93
|
end
|
94
94
|
|
95
95
|
it_should_behave_like 'An Adapter'
|
@@ -120,7 +120,7 @@ describe DataMapper::Adapters::PersevereAdapter do
|
|
120
120
|
it 'should create the json schema for the hash under the specified project' do
|
121
121
|
@adapter.put_schema(@test_schema_hash_alt).should_not == false
|
122
122
|
end
|
123
|
-
|
123
|
+
end
|
124
124
|
|
125
125
|
describe '#get_schema' do
|
126
126
|
it 'should return all of the schemas (in json) if no name is provided' do
|
@@ -306,4 +306,84 @@ describe DataMapper::Adapters::PersevereAdapter do
|
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
309
|
+
describe 'associations' do
|
310
|
+
before(:all) do
|
311
|
+
class ::BlogPost
|
312
|
+
include DataMapper::Resource
|
313
|
+
property :id, Serial
|
314
|
+
property :title, String
|
315
|
+
property :body, Text
|
316
|
+
|
317
|
+
# property :comment, JsonReference, :reference => ::Comment
|
318
|
+
end
|
319
|
+
|
320
|
+
class ::Comment
|
321
|
+
include DataMapper::Resource
|
322
|
+
property :id, Serial
|
323
|
+
property :contents, Text
|
324
|
+
property :rating, Integer
|
325
|
+
|
326
|
+
property :blog_post, JsonReference, :reference => BlogPost
|
327
|
+
end
|
328
|
+
|
329
|
+
class ::Author
|
330
|
+
include DataMapper::Resource
|
331
|
+
property :id, Serial
|
332
|
+
property :name, String
|
333
|
+
end
|
334
|
+
|
335
|
+
class ::Address
|
336
|
+
include DataMapper::Resource
|
337
|
+
property :id, Serial
|
338
|
+
property :addr, String
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
before(:each) do
|
343
|
+
BlogPost.auto_migrate!
|
344
|
+
Author.auto_migrate!
|
345
|
+
Comment.auto_migrate!
|
346
|
+
Address.auto_migrate!
|
347
|
+
BlogPost.send(:property, :comments, DataMapper::Types::JsonReferenceCollection, :reference => Comment)
|
348
|
+
BlogPost.auto_migrate!
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should create associations between models" do
|
352
|
+
|
353
|
+
# Create the instances
|
354
|
+
bpost = BlogPost.create(:title => "Test Post", :body => "This is the body of the test post.")
|
355
|
+
comment = Comment.new(:contents => "I think the post is great!", :rating => 4)
|
356
|
+
comment.blog_post = bpost
|
357
|
+
# bpost.comment = comment
|
358
|
+
# bpost.save
|
359
|
+
comment.save
|
360
|
+
|
361
|
+
Comment.first.blog_post.should be_kind_of(BlogPost)
|
362
|
+
Comment.first.blog_post.id.should eql(1)
|
363
|
+
|
364
|
+
# confirm it actually works with tests
|
365
|
+
# bpost.comments.length.should eql 2
|
366
|
+
end
|
367
|
+
|
368
|
+
it "should be able to handle collections of relationships" do
|
369
|
+
bpost = BlogPost.new(:title => "A new post", :body => "This one will have many comments")
|
370
|
+
|
371
|
+
bpost.comments = [Comment.new(:contents => "This is the best", :rating => 5)]
|
372
|
+
bpost.save
|
373
|
+
BlogPost.first.comments.should be_kind_of(Array)
|
374
|
+
BlogPost.first.comments.length.should eql(1)
|
375
|
+
BlogPost.first.comments.first.should be_kind_of(Comment)
|
376
|
+
|
377
|
+
bpost.comments << Comment.new(:contents => "No, this is the best!", :rating => 3)
|
378
|
+
bpost.save
|
379
|
+
BlogPost.first.comments.length.should eql(2)
|
380
|
+
end
|
381
|
+
|
382
|
+
after(:all) do
|
383
|
+
BlogPost.auto_migrate_down!
|
384
|
+
Author.auto_migrate_down!
|
385
|
+
Address.auto_migrate_down!
|
386
|
+
Comment.auto_migrate_down!
|
387
|
+
end
|
388
|
+
end
|
309
389
|
end
|
data/spec/persevere_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-persevere-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 48
|
8
|
+
- 0
|
9
|
+
version: 0.48.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Ivan R. Judson
|
@@ -10,29 +15,35 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2010-
|
18
|
+
date: 2010-04-16 00:00:00 -06:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
17
22
|
name: dm-core
|
18
|
-
|
19
|
-
|
20
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
25
|
requirements:
|
22
26
|
- - ">="
|
23
27
|
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 10
|
31
|
+
- 1
|
24
32
|
version: 0.10.1
|
25
|
-
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
26
35
|
- !ruby/object:Gem::Dependency
|
27
36
|
name: extlib
|
28
|
-
|
29
|
-
|
30
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
39
|
requirements:
|
32
40
|
- - ">="
|
33
41
|
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
34
44
|
version: "0"
|
35
|
-
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
36
47
|
description: A DataMapper Adapter for persevere
|
37
48
|
email:
|
38
49
|
- irjudson [a] gmail [d] com
|
@@ -54,6 +65,8 @@ files:
|
|
54
65
|
- lib/model_json_support.rb
|
55
66
|
- lib/persevere.rb
|
56
67
|
- lib/persevere_adapter.rb
|
68
|
+
- lib/types/json_reference.rb
|
69
|
+
- lib/types/json_reference_collection.rb
|
57
70
|
- persevere/History.txt
|
58
71
|
- persevere/LICENSE.txt
|
59
72
|
- persevere/Manifest.txt
|
@@ -77,18 +90,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
90
|
requirements:
|
78
91
|
- - ">="
|
79
92
|
- !ruby/object:Gem::Version
|
93
|
+
segments:
|
94
|
+
- 0
|
80
95
|
version: "0"
|
81
|
-
version:
|
82
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
97
|
requirements:
|
84
98
|
- - ">="
|
85
99
|
- !ruby/object:Gem::Version
|
100
|
+
segments:
|
101
|
+
- 0
|
86
102
|
version: "0"
|
87
|
-
version:
|
88
103
|
requirements: []
|
89
104
|
|
90
105
|
rubyforge_project:
|
91
|
-
rubygems_version: 1.3.
|
106
|
+
rubygems_version: 1.3.6
|
92
107
|
signing_key:
|
93
108
|
specification_version: 3
|
94
109
|
summary: A DataMapper Adapter for persevere
|