dm-persevere-adapter 0.70.0 → 0.71.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/persevere.rb +25 -11
- data/lib/persevere_adapter.rb +28 -32
- data/spec/persevere_adapter_spec.rb +59 -1
- metadata +13 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.71.0
|
data/lib/persevere.rb
CHANGED
@@ -59,18 +59,24 @@ class Persevere
|
|
59
59
|
def initialize(url)
|
60
60
|
@server_url = url
|
61
61
|
server = URI.parse(@server_url)
|
62
|
-
@
|
62
|
+
@base_uri = server.path || ''
|
63
63
|
@persevere = Net::HTTP.new(server.host, server.port)
|
64
|
+
@client_id = "dm-persevere-adapter-#{(rand*1000)}" # just need a small random string
|
65
|
+
@sequence_id = 0
|
64
66
|
end
|
65
67
|
|
66
68
|
# Pass in a resource hash
|
67
69
|
def create(path, resource, headers = {})
|
68
|
-
path = @
|
69
|
-
|
70
|
+
path = @base_uri + path
|
71
|
+
if headers.has_key?('Content-Type') && headers['Content-Type'] != 'application/json'
|
72
|
+
json_blob = resource
|
73
|
+
else
|
74
|
+
json_blob = resource.delete_if{|key,value| value.nil? }.to_json
|
75
|
+
end
|
70
76
|
response = nil
|
71
77
|
while response.nil?
|
72
78
|
begin
|
73
|
-
response = @persevere.send_request('POST', URI.encode(path), json_blob,
|
79
|
+
response = @persevere.send_request('POST', URI.encode(path), json_blob, default_headers.merge(headers))
|
74
80
|
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
75
81
|
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
76
82
|
puts "Persevere Create Failed: #{e}, Trying again."
|
@@ -80,11 +86,11 @@ class Persevere
|
|
80
86
|
end
|
81
87
|
|
82
88
|
def retrieve(path, headers = {})
|
83
|
-
path = @
|
89
|
+
path = @base_uri + path
|
84
90
|
response = nil
|
85
91
|
while response.nil?
|
86
92
|
begin
|
87
|
-
response = @persevere.send_request('GET', URI.encode(path), nil,
|
93
|
+
response = @persevere.send_request('GET', URI.encode(path), nil, default_headers.merge(headers))
|
88
94
|
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
89
95
|
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
90
96
|
puts "Persevere Retrieve Failed: #{e}, Trying again."
|
@@ -94,12 +100,12 @@ class Persevere
|
|
94
100
|
end
|
95
101
|
|
96
102
|
def update(path, resource, headers = {})
|
97
|
-
path = @
|
103
|
+
path = @base_uri + path
|
98
104
|
json_blob = resource.to_json
|
99
105
|
response = nil
|
100
106
|
while response.nil?
|
101
107
|
begin
|
102
|
-
response = @persevere.send_request('PUT', URI.encode(path), json_blob,
|
108
|
+
response = @persevere.send_request('PUT', URI.encode(path), json_blob, default_headers.merge(headers))
|
103
109
|
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
104
110
|
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
105
111
|
puts "Persevere Create Failed: #{e}, Trying again."
|
@@ -109,11 +115,11 @@ class Persevere
|
|
109
115
|
end
|
110
116
|
|
111
117
|
def delete(path, headers = {})
|
112
|
-
path = @
|
118
|
+
path = @base_uri + path
|
113
119
|
response = nil
|
114
120
|
while response.nil?
|
115
121
|
begin
|
116
|
-
response = @persevere.send_request('DELETE', URI.encode(path), nil,
|
122
|
+
response = @persevere.send_request('DELETE', URI.encode(path), nil, default_headers.merge(headers))
|
117
123
|
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
118
124
|
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
119
125
|
puts "Persevere Create Failed: #{e}, Trying again."
|
@@ -121,4 +127,12 @@ class Persevere
|
|
121
127
|
end
|
122
128
|
return PersevereResult.make(response)
|
123
129
|
end
|
124
|
-
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def default_headers
|
134
|
+
@sequence_id += 1
|
135
|
+
HEADERS.merge( {'Seq-Id' => @sequence_id.to_s, 'Client-Id' => @client_id } )
|
136
|
+
end
|
137
|
+
|
138
|
+
end # class Persevere
|
data/lib/persevere_adapter.rb
CHANGED
@@ -267,8 +267,7 @@ module DataMapper
|
|
267
267
|
path = "/#{resource.model.storage_name}/"
|
268
268
|
# Invoke to_json_hash with a boolean to indicate this is a create
|
269
269
|
# We might want to make this a post-to_json_hash cleanup instead
|
270
|
-
payload = resource.to_json_hash(false)
|
271
|
-
# scrub_data(payload)
|
270
|
+
payload = resource.to_json_hash(false).delete_if{|key,value| value.nil? }
|
272
271
|
DataMapper.logger.debug("--> PATH/PAYLOAD: #{path} #{payload.inspect}")
|
273
272
|
response = @persevere.create(path, payload)
|
274
273
|
|
@@ -332,7 +331,6 @@ module DataMapper
|
|
332
331
|
tblname = resource.model.storage_name
|
333
332
|
path = "/#{tblname}/#{resource.key.first}"
|
334
333
|
payload = resource.to_json_hash()
|
335
|
-
# scrub_data(payload)
|
336
334
|
DataMapper.logger.debug("--> PATH/PAYLOAD: #{path} #{payload.inspect}")
|
337
335
|
result = @persevere.update(path, payload)
|
338
336
|
|
@@ -381,8 +379,6 @@ module DataMapper
|
|
381
379
|
# @api semipublic
|
382
380
|
def read_many(query)
|
383
381
|
connect if @persevere.nil?
|
384
|
-
|
385
|
-
# check_schemas
|
386
382
|
|
387
383
|
resources = Array.new
|
388
384
|
tblname = query.model.storage_name
|
@@ -411,15 +407,11 @@ module DataMapper
|
|
411
407
|
if value.is_a?(Hash)
|
412
408
|
if value.has_key?("$ref")
|
413
409
|
value = value["$ref"].split("/")[-1]
|
414
|
-
else
|
415
|
-
# value = value["id"].split("/")[-1]
|
416
410
|
end
|
417
411
|
elsif value.is_a?(Array)
|
418
412
|
value = value.map do |v|
|
419
413
|
if v.has_key?("$ref")
|
420
414
|
v = v["$ref"].split("/")[-1]
|
421
|
-
else
|
422
|
-
# v = v["id"].split("/")[-1]
|
423
415
|
end
|
424
416
|
end
|
425
417
|
end
|
@@ -470,8 +462,6 @@ module DataMapper
|
|
470
462
|
connect if @persevere.nil?
|
471
463
|
|
472
464
|
deleted = 0
|
473
|
-
|
474
|
-
# check_schemas
|
475
465
|
|
476
466
|
if ! query.is_a?(DataMapper::Query)
|
477
467
|
resources = [query].flatten
|
@@ -500,8 +490,6 @@ module DataMapper
|
|
500
490
|
def get_schema(name = nil, project = nil)
|
501
491
|
path = nil
|
502
492
|
single = false
|
503
|
-
|
504
|
-
# check_schemas
|
505
493
|
|
506
494
|
if name.nil? & project.nil?
|
507
495
|
path = "/Class/"
|
@@ -520,7 +508,6 @@ module DataMapper
|
|
520
508
|
schema['properties']['id'] = { 'type' => "serial", 'index' => true }
|
521
509
|
end
|
522
510
|
end
|
523
|
-
# save_schemas
|
524
511
|
|
525
512
|
return name.nil? ? schemas : schemas[0..0]
|
526
513
|
else
|
@@ -542,14 +529,11 @@ module DataMapper
|
|
542
529
|
end
|
543
530
|
end
|
544
531
|
|
545
|
-
# check_schemas
|
546
|
-
|
547
532
|
scrub_schema(schema_hash['properties'])
|
548
533
|
schema_hash['extends'] = { "$ref" => "/Class/Versioned" } if @options[:versioned]
|
549
|
-
|
534
|
+
schema_hash.delete_if{|key,value| value.nil? }
|
550
535
|
result = @persevere.create(path, schema_hash)
|
551
536
|
if result.code == '201'
|
552
|
-
# save_schemas
|
553
537
|
|
554
538
|
return JSON.parse(result.body)
|
555
539
|
else
|
@@ -565,8 +549,6 @@ module DataMapper
|
|
565
549
|
scrub_schema(payload['properties'])
|
566
550
|
payload['extends'] = { "$ref" => "/Class/Versioned" } if @options[:versioned]
|
567
551
|
|
568
|
-
# check_schemas
|
569
|
-
|
570
552
|
if project.nil?
|
571
553
|
path = "/Class/#{id}"
|
572
554
|
else
|
@@ -576,7 +558,6 @@ module DataMapper
|
|
576
558
|
result = @persevere.update(path, payload)
|
577
559
|
|
578
560
|
if result.code == '200'
|
579
|
-
# save_schemas
|
580
561
|
return result.body
|
581
562
|
else
|
582
563
|
return false
|
@@ -595,14 +576,11 @@ module DataMapper
|
|
595
576
|
DataMapper.logger.error("You need an id key/value in the hash")
|
596
577
|
end
|
597
578
|
end
|
598
|
-
|
599
|
-
# check_schemas
|
600
|
-
|
579
|
+
|
601
580
|
path = "/Class/#{schema_hash['id']}"
|
602
581
|
result = @persevere.delete(path)
|
603
582
|
|
604
583
|
if result.code == "204"
|
605
|
-
# save_schemas
|
606
584
|
return true
|
607
585
|
else
|
608
586
|
return false
|
@@ -642,7 +620,12 @@ module DataMapper
|
|
642
620
|
@options[:scheme] = @options[:adapter]
|
643
621
|
@options.delete(:scheme)
|
644
622
|
|
645
|
-
@resource_naming_convention = NamingConventions::Resource::Underscored
|
623
|
+
# @resource_naming_convention = NamingConventions::Resource::Underscored
|
624
|
+
@resource_naming_convention = lambda do |value|
|
625
|
+
# value.split('::').map{ |val| Extlib::Inflection.underscore(val) }.join('__')
|
626
|
+
Extlib::Inflection.underscore(value).gsub('/', '__')
|
627
|
+
end
|
628
|
+
|
646
629
|
@identity_maps = {}
|
647
630
|
@persevere = nil
|
648
631
|
@prepped = false
|
@@ -729,7 +712,7 @@ module DataMapper
|
|
729
712
|
# If the user specified a versioned datastore load the versioning REST code
|
730
713
|
#
|
731
714
|
unless get_classes.include?("Versioned") && @options[:versioned]
|
732
|
-
versioned_class
|
715
|
+
versioned_class =<<-EOF
|
733
716
|
{
|
734
717
|
id: "Versioned",
|
735
718
|
prototype: {
|
@@ -775,12 +758,25 @@ module DataMapper
|
|
775
758
|
}
|
776
759
|
}
|
777
760
|
EOF
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
761
|
+
|
762
|
+
response = @persevere.create('/Class/', versioned_class, { 'Content-Type' => 'application/javascript' } )
|
763
|
+
|
764
|
+
# Check the response, this needs to be more robust and raise
|
765
|
+
# exceptions when there's a problem
|
766
|
+
if response.code == "201"# good:
|
767
|
+
DataMapper.logger.info("Created versioned class.")
|
768
|
+
else
|
769
|
+
DataMapper.logger.info("Failed to create versioned class.")
|
783
770
|
end
|
771
|
+
|
772
|
+
# headers = { 'Content-Type' => 'application/javascript', 'Accept' => 'application/json' }
|
773
|
+
# begin
|
774
|
+
# puts "POST #{URI.encode('/Class')}, #{versioned_class}, #{headers.inspect}"
|
775
|
+
# response = @persevere.persevere.send_request('POST', URI.encode('/Class/'), versioned_class, headers )
|
776
|
+
# rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
777
|
+
# Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
778
|
+
# DataMapper.logger.error("Persevere Create Failed: #{e}, Trying again.")
|
779
|
+
# end
|
784
780
|
end
|
785
781
|
end
|
786
782
|
end # class PersevereAdapter
|
@@ -11,7 +11,7 @@ require Pathname(__FILE__).dirname.expand_path.parent + 'lib/persevere_adapter'
|
|
11
11
|
|
12
12
|
describe DataMapper::Adapters::PersevereAdapter do
|
13
13
|
before :all do
|
14
|
-
DataMapper::Logger.new(STDOUT, :debug)
|
14
|
+
# DataMapper::Logger.new(STDOUT, :debug)
|
15
15
|
@adapter = DataMapper.setup(:default, {
|
16
16
|
:adapter => 'persevere',
|
17
17
|
:host => 'localhost',
|
@@ -518,6 +518,64 @@ describe DataMapper::Adapters::PersevereAdapter do
|
|
518
518
|
|
519
519
|
Bozon.first.nugatons.length.should be(1)
|
520
520
|
end
|
521
|
+
|
522
|
+
it "should remove resources from both sides of the relationship when there are many on each side" do
|
523
|
+
|
524
|
+
bozon1 = Bozon.create(:author => 'Jade', :title => "Jade's the author")
|
525
|
+
bozon2 = Bozon.create(:author => 'Ivan', :title => "Blow up the world!")
|
526
|
+
nugat1 = Nugaton.new(:name => "numero uno")
|
527
|
+
nugat2 = Nugaton.new(:name => "numero duo")
|
528
|
+
|
529
|
+
bozon1.nugatons.push(nugat1, nugat2)
|
530
|
+
bozon2.nugatons = [nugat1,nugat2]
|
531
|
+
bozon1.save
|
532
|
+
bozon2.save
|
533
|
+
|
534
|
+
bozon1.nugatons.delete(nugat1)
|
535
|
+
bozon1.save
|
536
|
+
|
537
|
+
# Bozon1 should have only nugaton2
|
538
|
+
Bozon.get(bozon1.id).nugatons.length.should eql 1
|
539
|
+
Bozon.get(bozon1.id).nugatons.should_not include(nugat1)
|
540
|
+
Bozon.get(bozon1.id).nugatons.should include(nugat2)
|
541
|
+
|
542
|
+
# Bozon2 should have both nugatons
|
543
|
+
Bozon.get(bozon2.id).nugatons.length.should eql 2
|
544
|
+
Bozon.get(bozon2.id).nugatons.should include(nugat1)
|
545
|
+
Bozon.get(bozon2.id).nugatons.should include(nugat2)
|
546
|
+
|
547
|
+
# Nugaton1 should have Bozon2
|
548
|
+
Nugaton.get(nugat1.id).bozons.length.should eql 1
|
549
|
+
Nugaton.get(nugat1.id).bozons.should_not include(bozon1)
|
550
|
+
Nugaton.get(nugat1.id).bozons.should include(bozon2)
|
551
|
+
|
552
|
+
# Nugaton2 should have both bozons
|
553
|
+
Nugaton.get(nugat2.id).bozons.length.should eql 2
|
554
|
+
Nugaton.get(nugat2.id).bozons.should include(bozon1)
|
555
|
+
Nugaton.get(nugat2.id).bozons.should include(bozon2)
|
556
|
+
end
|
557
|
+
|
558
|
+
it "should act sanely" do
|
559
|
+
Bozon.has(Infinity, :nugatons, {:through => DataMapper::Resource})
|
560
|
+
Nugaton.has(Infinity, :bozons, {:through => DataMapper::Resource})
|
561
|
+
Bozon.auto_upgrade!
|
562
|
+
Nugaton.auto_upgrade!
|
563
|
+
|
564
|
+
bozon = Bozon.create(:author => 'Jade', :title => "Jade's the author")
|
565
|
+
|
566
|
+
nugat1 = Nugaton.create(:name => "numero uno")
|
567
|
+
nugat2 = Nugaton.create(:name => "numero duo")
|
568
|
+
|
569
|
+
nugat1.bozons << bozon
|
570
|
+
nugat1.save
|
571
|
+
|
572
|
+
n = Nugaton.get(nugat2.id)
|
573
|
+
n.bozons << Bozon.first
|
574
|
+
n.save
|
575
|
+
|
576
|
+
Bozon.get(bozon.id).nugatons.length.should eql 2
|
577
|
+
|
578
|
+
end
|
521
579
|
|
522
580
|
end
|
523
581
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-persevere-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 259
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
+
- 71
|
8
9
|
- 0
|
9
|
-
version: 0.
|
10
|
+
version: 0.71.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Ivan R. Judson
|
@@ -15,16 +16,18 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2010-
|
19
|
+
date: 2010-07-01 00:00:00 -06:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
22
23
|
name: dm-core
|
23
24
|
prerelease: false
|
24
25
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
25
27
|
requirements:
|
26
28
|
- - ">="
|
27
29
|
- !ruby/object:Gem::Version
|
30
|
+
hash: 51
|
28
31
|
segments:
|
29
32
|
- 0
|
30
33
|
- 10
|
@@ -36,9 +39,11 @@ dependencies:
|
|
36
39
|
name: extlib
|
37
40
|
prerelease: false
|
38
41
|
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
39
43
|
requirements:
|
40
44
|
- - ">="
|
41
45
|
- !ruby/object:Gem::Version
|
46
|
+
hash: 3
|
42
47
|
segments:
|
43
48
|
- 0
|
44
49
|
version: "0"
|
@@ -90,23 +95,27 @@ rdoc_options:
|
|
90
95
|
require_paths:
|
91
96
|
- lib
|
92
97
|
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
93
99
|
requirements:
|
94
100
|
- - ">="
|
95
101
|
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
96
103
|
segments:
|
97
104
|
- 0
|
98
105
|
version: "0"
|
99
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
100
108
|
requirements:
|
101
109
|
- - ">="
|
102
110
|
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
103
112
|
segments:
|
104
113
|
- 0
|
105
114
|
version: "0"
|
106
115
|
requirements: []
|
107
116
|
|
108
117
|
rubyforge_project:
|
109
|
-
rubygems_version: 1.3.
|
118
|
+
rubygems_version: 1.3.7
|
110
119
|
signing_key:
|
111
120
|
specification_version: 3
|
112
121
|
summary: A DataMapper Adapter for persevere
|