dm-persevere-adapter 0.47.1 → 0.48.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/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
|