dm-rest-adapter 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,4 +23,4 @@ stories/helper.rb
23
23
  stories/resources/helpers/book.rb
24
24
  stories/resources/helpers/story_helper.rb
25
25
  stories/resources/steps/read.rb
26
- stories/resources/steps/using_rest_adapter.rb
26
+ stories/resources/steps/using_rest_adapter.rb
@@ -3,7 +3,10 @@ require 'pathname'
3
3
  require Pathname(__FILE__).dirname + 'rest_adapter/version'
4
4
  gem 'dm-core', DataMapper::More::RestAdapter::VERSION
5
5
  require 'dm-core'
6
+
7
+ gem 'extlib', '=0.9.4'
6
8
  require 'extlib'
9
+
7
10
  require 'dm-serializer'
8
11
  require 'net/http'
9
12
  require 'rexml/document'
@@ -14,7 +17,7 @@ module DataMapper
14
17
  module Adapters
15
18
  class RestAdapter < AbstractAdapter
16
19
  include Extlib
17
-
20
+
18
21
  # Creates a new resource in the specified repository.
19
22
  def create(resources)
20
23
  count = 0
@@ -22,7 +25,7 @@ module DataMapper
22
25
  resource_name = Inflection.underscore(resource.class.name)
23
26
  result = http_post("/#{resource_name.pluralize}.xml", resource.to_xml)
24
27
  # TODO: Raise error if cannot reach server
25
- success = result.instance_of?(Net::HTTPCreated)
28
+ success = result.instance_of?(Net::HTTPCreated)
26
29
  if success
27
30
  count += 1
28
31
  # TODO: Fix commented out code below to work through the identity_map of the repository
@@ -33,7 +36,7 @@ module DataMapper
33
36
  end
34
37
  count
35
38
  end
36
-
39
+
37
40
  # read_set
38
41
  #
39
42
  # Examples of query string:
@@ -62,7 +65,7 @@ module DataMapper
62
65
  end
63
66
  end
64
67
  end
65
-
68
+
66
69
  def read_one(query)
67
70
  resource = nil
68
71
  resource_name = resource_name_from_query(query)
@@ -73,16 +76,16 @@ module DataMapper
73
76
  else
74
77
  id = query.conditions.first[2]
75
78
  # KLUGE: Again, we're assuming below that we're dealing with a pluralized resource mapping
76
-
79
+
77
80
  response = http_get("/#{resource_name.pluralize}/#{id}.xml")
78
-
81
+
79
82
  # KLUGE: Rails returns HTML if it can't find a resource. A properly RESTful app would return a 404, right?
80
83
  return nil if response.is_a? Net::HTTPNotFound || response.content_type == "text/html"
81
-
84
+
82
85
  data = response.body
83
86
  resource_meta = parse_resource(data, query.model, query)
84
87
  end
85
- if resource_meta
88
+ if resource_meta
86
89
  if resource_meta.has_key?(:associations)
87
90
  load_nested_resources_from resource_meta[:associations], query
88
91
  end
@@ -90,13 +93,13 @@ module DataMapper
90
93
  end
91
94
  resource
92
95
  end
93
-
96
+
94
97
  def update(attributes, query)
95
98
  # TODO What if we have a compound key?
96
99
  raise NotImplementedError.new unless is_single_resource_query? query
97
100
  id = query.conditions.first[2]
98
101
  resource = nil
99
- query.repository.scope do
102
+ query.repository.scope do
100
103
  resource = query.model.get(id)
101
104
  end
102
105
  attributes.each do |attr, val|
@@ -107,15 +110,15 @@ module DataMapper
107
110
  # TODO: Raise error if cannot reach server
108
111
  res.kind_of?(Net::HTTPSuccess) ? 1 : 0
109
112
  end
110
-
113
+
111
114
  def delete(query)
112
115
  raise NotImplementedError.new unless is_single_resource_query? query
113
116
  id = query.conditions.first[2]
114
117
  res = http_delete("/#{resource_name_from_query(query).pluralize}/#{id}.xml")
115
118
  res.kind_of?(Net::HTTPSuccess) ? 1 : 0
116
119
  end
117
-
118
- protected
120
+
121
+ protected
119
122
  def load_nested_resources_from(nested_resources, query)
120
123
  nested_resources.each do |resource_meta|
121
124
  # TODO: Houston, we have a problem. Model#load expects a Query. When we're nested, we don't have a query yet...
@@ -125,7 +128,7 @@ module DataMapper
125
128
  #end
126
129
  end
127
130
  end
128
-
131
+
129
132
  def read_set_all(repository, query, resource_name)
130
133
  # TODO: how do we know whether the resource we're talking to is singular or plural?
131
134
  res = http_get("/#{resource_name.pluralize}.xml")
@@ -133,18 +136,18 @@ module DataMapper
133
136
  parse_resources(data, query.model, query)
134
137
  # TODO: Raise error if cannot reach server
135
138
  end
136
-
139
+
137
140
  # GET /books/4200
138
141
  def read_set_for_condition(repository, query, resource_name)
139
142
  # More complex conditions
140
143
  raise NotImplementedError.new
141
- end
142
-
144
+ end
145
+
143
146
  # query.conditions like [[:eql, #<Property:Book:id>, 4200]]
144
147
  def is_single_resource_query?(query)
145
148
  query.conditions.length == 1 && query.conditions.first.first == :eql && query.conditions.first[1].name == :id
146
149
  end
147
-
150
+
148
151
  def http_put(uri, data = nil)
149
152
  request { |http| http.put(uri, data, {"Content-Type", "application/xml"}) }
150
153
  end
@@ -167,13 +170,13 @@ module DataMapper
167
170
  res = yield(http)
168
171
  end
169
172
  res
170
- end
173
+ end
171
174
 
172
175
  def values_from_rexml(entity_element, dm_model_class)
173
176
  resource = {}
174
177
  resource[:values] = []
175
178
  entity_element.elements.each do |field_element|
176
- attribute = dm_model_class.properties(repository.name).find do |property|
179
+ attribute = dm_model_class.properties(repository.name).find do |property|
177
180
  # *MUST* use Inflection.underscore on the XML as Rails converts '_' to '-' in the XML
178
181
  property.name.to_s == Inflection.underscore(field_element.name.to_s)
179
182
  end
@@ -188,7 +191,7 @@ module DataMapper
188
191
  field_element.each_element do |associated_element|
189
192
  model = association[1].child_model
190
193
  (resource[:associations] ||= []) << {
191
- :model => model,
194
+ :model => model,
192
195
  :value => values_from_rexml(associated_element, association[1].child_model)
193
196
  }
194
197
  end
@@ -204,7 +207,7 @@ module DataMapper
204
207
  return nil unless entity_element
205
208
  values_from_rexml(entity_element, dm_model_class)
206
209
  end
207
-
210
+
208
211
  def parse_resources(xml, dm_model_class, query = nil)
209
212
  doc = REXML::Document::new(xml)
210
213
  # # TODO: handle singular resource case as well....
@@ -216,15 +219,15 @@ module DataMapper
216
219
  doc.elements.collect("#{resource_name.pluralize}/#{resource_name}") do |entity_element|
217
220
  values_from_rexml(entity_element, dm_model_class)
218
221
  end
219
- end
220
-
222
+ end
223
+
221
224
  def resource_name_from_model(model)
222
225
  Inflection.underscore(model.name)
223
226
  end
224
-
227
+
225
228
  def resource_name_from_query(query)
226
229
  resource_name_from_model(query.model)
227
230
  end
228
231
  end
229
232
  end
230
- end
233
+ end
@@ -1,7 +1,7 @@
1
1
  module DataMapper
2
2
  module More
3
3
  class RestAdapter
4
- VERSION = "0.9.3"
4
+ VERSION = "0.9.4"
5
5
  end
6
6
  end
7
- end
7
+ end
@@ -2,20 +2,20 @@ $LOAD_PATH << File.dirname(__FILE__)
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'A REST adapter' do
5
-
5
+
6
6
  before do
7
7
  @adapter = DataMapper::Repository.adapters[:default]
8
8
  end
9
-
9
+
10
10
  describe 'when saving a resource' do
11
-
11
+
12
12
  before do
13
13
  @book = Book.new(:title => 'Hello, World!', :author => 'Anonymous')
14
14
  end
15
-
15
+
16
16
  it 'should make an HTTP Post' do
17
17
  @adapter.should_receive(:http_post).with('/books.xml', @book.to_xml)
18
18
  @book.save
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -2,21 +2,21 @@ $LOAD_PATH << File.dirname(__FILE__)
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'A REST adapter' do
5
-
5
+
6
6
  before do
7
7
  @adapter = DataMapper::Repository.adapters[:default]
8
8
  end
9
-
9
+
10
10
  describe 'when deleting an existing resource' do
11
11
  before do
12
12
  @book = Book.new(:title => 'Hello, World!', :author => 'Anonymous')
13
13
  @book.stub!(:new_record?).and_return(false)
14
14
  end
15
-
15
+
16
16
  it 'should do an HTTP DELETE' do
17
17
  @adapter.should_receive(:http_delete)
18
18
  @book.destroy
19
19
  end
20
-
20
+
21
21
  end
22
- end
22
+ end
@@ -2,15 +2,15 @@ $LOAD_PATH << File.dirname(__FILE__)
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'A REST adapter' do
5
-
5
+
6
6
  before do
7
7
  @adapter = DataMapper::Repository.adapters[:default]
8
8
  end
9
-
9
+
10
10
  describe 'when getting one resource' do
11
11
 
12
12
  describe 'if the resource exists' do
13
-
13
+
14
14
  before do
15
15
  book_xml = <<-BOOK
16
16
  <?xml version='1.0' encoding='UTF-8'?>
@@ -27,25 +27,25 @@ describe 'A REST adapter' do
27
27
  @response.stub!(:body).and_return(book_xml)
28
28
  @adapter.stub!(:http_get).and_return(@response)
29
29
  end
30
-
30
+
31
31
  it 'should return the resource' do
32
32
  book = Book.get(@id)
33
33
  book.should_not be_nil
34
34
  book.id.should be_an_instance_of(Fixnum)
35
35
  book.id.should == 1
36
36
  end
37
-
37
+
38
38
  it 'should do an HTTP GET' do
39
39
  @adapter.should_receive(:http_get).with('/books/1.xml').and_return(@response)
40
40
  Book.get(@id)
41
41
  end
42
-
42
+
43
43
  it "it be equal to itself" do
44
44
  Book.get(@id).should == Book.get(@id)
45
- end
45
+ end
46
46
  end
47
-
48
-
47
+
48
+
49
49
  describe 'if the resource does not exist' do
50
50
  it 'should return nil' do
51
51
  @id = 1
@@ -58,9 +58,9 @@ describe 'A REST adapter' do
58
58
  end
59
59
  end
60
60
  end
61
-
61
+
62
62
  describe 'when getting all resource of a particular type' do
63
- before do
63
+ before do
64
64
  books_xml = <<-BOOK
65
65
  <?xml version='1.0' encoding='UTF-8'?>
66
66
  <books type='array'>
@@ -70,7 +70,7 @@ describe 'A REST adapter' do
70
70
  <id type='integer'>1</id>
71
71
  <title>The Dispossed</title>
72
72
  <updated-at type='datetime'>2008-06-08T17:02:28Z</updated-at>
73
- </book>
73
+ </book>
74
74
  <book>
75
75
  <author>Stephen King</author>
76
76
  <created-at type='datetime'>2008-06-08T17:03:07Z</created-at>
@@ -84,18 +84,18 @@ describe 'A REST adapter' do
84
84
  @response.stub!(:body).and_return(books_xml)
85
85
  @adapter.stub!(:http_get).and_return(@response)
86
86
  end
87
-
87
+
88
88
  it 'should get a non-empty list' do
89
89
  Book.all.should_not be_empty
90
90
  end
91
-
91
+
92
92
  it 'should receive one Resource for each entity in the XML' do
93
93
  Book.all.size.should == 2
94
94
  end
95
-
95
+
96
96
  it 'should do an HTTP GET' do
97
97
  @adapter.should_receive(:http_get).and_return(@response)
98
98
  Book.first
99
- end
99
+ end
100
100
  end
101
- end
101
+ end
@@ -10,4 +10,4 @@ module RubyForker
10
10
  cmd << " 2> #{stderr}" unless stderr.nil?
11
11
  `#{cmd}`
12
12
  end
13
- end
13
+ end
@@ -2,7 +2,7 @@ $LOAD_PATH << File.dirname(__FILE__)
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'A REST adapter' do
5
-
5
+
6
6
  describe 'when updating an existing resource' do
7
7
  before do
8
8
  @books_xml = <<-XML
@@ -16,11 +16,11 @@ describe 'A REST adapter' do
16
16
  repository do |repo|
17
17
  @repository = repo
18
18
  @book = Book.new(:id => 42,
19
- :title => 'Starship Troopers',
20
- :author => 'Robert Heinlein',
19
+ :title => 'Starship Troopers',
20
+ :author => 'Robert Heinlein',
21
21
  :created_at => DateTime.parse('2008-06-08T17:02:28Z'))
22
22
  @book.instance_eval { @new_record = false }
23
- @repository.identity_map(Book).set(@book.key, @book)
23
+ @repository.identity_map(Book).set(@book.key, @book)
24
24
  @book.title = "Mary Had a Little Lamb"
25
25
  end
26
26
  end
@@ -28,9 +28,9 @@ describe 'A REST adapter' do
28
28
  it 'should do an HTTP PUT' do
29
29
  adapter = @repository.adapter #DataMapper::Repository.adapters[:default]
30
30
  adapter.should_receive(:http_put).with('/books/42.xml', @book.to_xml)
31
- @repository.scope do
31
+ @repository.scope do
32
32
  @book.save
33
33
  end
34
34
  end
35
35
  end
36
- end
36
+ end
@@ -28,12 +28,12 @@ Story: remote app wants to create a resource
28
28
 
29
29
  Scenario: remote app supplies a new valid Resource associated with another new invalid Resource
30
30
  Given a new Resource
31
- And another new invalid Resource associted with the first
31
+ And another new invalid Resource associated with the first
32
32
  When I try to save the first Resource
33
33
  Neither Resource should save
34
34
 
35
35
  Scenario: remote app supplies a new invalid Resource associated with another new invalid Resource
36
36
  Given a new invalid Resource
37
- And another new invalid Resource associted with the first
37
+ And another new invalid Resource associated with the first
38
38
  When I try to save the first Resource
39
39
  Neither Resource should save
@@ -15,4 +15,4 @@ Dir["#{File.dirname(__FILE__)}/*"].each do |file|
15
15
  run file if File.file?(file)
16
16
  end
17
17
  end
18
- end
18
+ end
@@ -6,4 +6,4 @@ require 'dm-core'
6
6
  #require 'pathname'
7
7
  #require Pathname(__FILE__).dirname.parent.expand_path + '../../lib/rest_adapter'
8
8
  require File.join(File.dirname(__FILE__), *%w[resources helpers story_helper])
9
- require File.join(File.dirname(__FILE__), *%w[resources steps using_rest_adapter])
9
+ require File.join(File.dirname(__FILE__), *%w[resources steps using_rest_adapter])
@@ -1,2 +1,2 @@
1
1
  require 'spec/story'
2
- require File.dirname(__FILE__) + '/../../../spec/ruby_forker'
2
+ require File.dirname(__FILE__) + '/../../../spec/ruby_forker'
@@ -7,9 +7,9 @@ steps_for :read do
7
7
  has n, :books
8
8
  end
9
9
  end
10
-
10
+
11
11
  Given "the ID of an existing Resource that has associated Resources" do
12
- # Assuming that resource 1 is there.
12
+ # Assuming that resource 1 is there.
13
13
  # @type.first would do a GET; that's what we're testing
14
14
  @resource_id = 1
15
15
  end
@@ -21,15 +21,15 @@ steps_for :read do
21
21
  When "I GET <nested resource>/<id>" do
22
22
  @resource = Shelf.get(@resource_id)
23
23
  end
24
-
24
+
25
25
  Then "I should get the Resource" do
26
26
  @resource.should_not be_nil
27
27
  @resource.should be_an_instance_of(Shelf)
28
28
  @resource.id.should == 1
29
29
  end
30
-
30
+
31
31
  Then "the Resource will have associated Resources" do
32
32
  @resource.books.should_not be_empty
33
33
  @resource.books.first.should be_an_instance_of(Book)
34
34
  end
35
- end
35
+ end
@@ -39,18 +39,18 @@ steps_for :using_rest_adapter do
39
39
  @resource = Book.first
40
40
  @resource_id = @resource.id
41
41
  end
42
-
42
+
43
43
  When("I try to save the Resource") do
44
44
  @result = @resource.save
45
45
  end
46
-
46
+
47
47
  When("I request all of the Resources of that type") do
48
48
  require File.join(File.dirname(__FILE__), '..', 'helpers', 'book')
49
49
  @resources = Book.all
50
50
  end
51
-
51
+
52
52
  When("I request the Resource") do
53
- require File.join(File.dirname(__FILE__), '..', 'helpers', 'book')
53
+ require File.join(File.dirname(__FILE__), '..', 'helpers', 'book')
54
54
  @resource = Book.get(@resource_id)
55
55
  end
56
56
 
@@ -61,19 +61,19 @@ steps_for :using_rest_adapter do
61
61
  When("I make invalid changes to that Resource") do
62
62
  @resource.title = nil
63
63
  end
64
-
64
+
65
65
  When("I destroy the Resource") do
66
66
  @resource.destroy
67
67
  end
68
-
68
+
69
69
  Then("the Resource should save") do
70
70
  @result.should be_true
71
71
  end
72
-
72
+
73
73
  Then("the Resource should not save") do
74
74
  @result.should be_false
75
75
  end
76
-
76
+
77
77
  Then("I should not receive an empty list") do
78
78
  @resources.should_not be_empty
79
79
  end
@@ -86,7 +86,7 @@ steps_for :using_rest_adapter do
86
86
  Then("I should get nothing in return") do
87
87
  @resource.should be_nil
88
88
  end
89
-
89
+
90
90
  Then("the Resource will no longer be available") do
91
91
  # TODO refactor
92
92
  require File.join(File.dirname(__FILE__), '..', 'helpers', 'book')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-rest-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Potomac Ruby Hackers
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-24 00:00:00 -05:00
12
+ date: 2008-08-21 00:00:00 -05: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.9.3
23
+ version: 0.9.4
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: hoe