rosemary 0.2.8 → 0.3.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/lib/rosemary/api.rb CHANGED
@@ -12,7 +12,6 @@ module Rosemary
12
12
  # api.save(@node)
13
13
  class Api
14
14
  include HTTParty
15
- include ChangesetCallbacks
16
15
  API_VERSION = "0.6".freeze
17
16
 
18
17
  # the default base URI for the API
@@ -31,10 +30,6 @@ module Rosemary
31
30
  @client = client
32
31
  end
33
32
 
34
- def changeset!
35
- @changeset ||= create_changeset
36
- end
37
-
38
33
  # Get a Node with specified ID from API.
39
34
  #
40
35
  # call-seq: find_node(id) -> Rosemary::Node
@@ -67,6 +62,21 @@ module Rosemary
67
62
  find_element('changeset', id)
68
63
  end
69
64
 
65
+ # Get a Changeset with specified ID from API
66
+ # if that changeset is missing, id is nil, or the changeset is closed
67
+ # create a new one
68
+ #
69
+ # call-seq: find_or_create_open_changeset(id, comment) -> Rosemary::Changeset
70
+ #
71
+ def find_or_create_open_changeset(id, comment = nil)
72
+ find_open_changeset(id) || create_changeset(comment)
73
+ end
74
+
75
+ def find_open_changeset(id)
76
+ cs = find_changeset(id)
77
+ (cs && cs.open?) ? cs : nil
78
+ end
79
+
70
80
  # Get the user which represented by the Rosemary::Client
71
81
  #
72
82
  # call-seq: find_user -> Rosemary::User
@@ -79,8 +89,7 @@ module Rosemary
79
89
  end
80
90
 
81
91
  # Delete an element
82
- def destroy(element)
83
- raise ChangesetMissing unless changeset.open?
92
+ def destroy(element, changeset)
84
93
  element.changeset = changeset.id
85
94
  response = delete("/#{element.type.downcase}/#{element.id}", :body => element.to_xml) unless element.id.nil?
86
95
  response.to_i # New version number
@@ -88,34 +97,32 @@ module Rosemary
88
97
 
89
98
  # Saves an element to the API.
90
99
  # If it has no id yet, the element will be created, otherwise updated.
91
- def save(element)
100
+ def save(element, changeset)
92
101
  response = if element.id.nil?
93
- create(element)
102
+ create(element, changeset)
94
103
  else
95
- update(element)
104
+ update(element, changeset)
96
105
  end
97
106
  end
98
107
 
99
- def create(element)
100
- raise ChangesetMissing unless changeset.open?
108
+ def create(element, changeset)
101
109
  element.changeset = changeset.id
102
110
  put("/#{element.type.downcase}/create", :body => element.to_xml)
103
111
  end
104
112
 
105
- def update(element)
106
- raise ChangesetMissing unless changeset.open?
113
+ def update(element, changeset)
107
114
  element.changeset = changeset.id
108
115
  response = put("/#{element.type.downcase}/#{element.id}", :body => element.to_xml)
109
116
  response.to_i # New Version number
110
117
  end
111
118
 
112
- def create_changeset
113
- changeset = Changeset.new
119
+ def create_changeset(comment = nil)
120
+ changeset = Changeset.new(:tags => { :comment => comment })
114
121
  changeset_id = put("/changeset/create", :body => changeset.to_xml).to_i
115
122
  find_changeset(changeset_id) unless changeset_id == 0
116
123
  end
117
124
 
118
- def close_changeset
125
+ def close_changeset(changeset)
119
126
  put("/changeset/#{changeset.id}/close")
120
127
  end
121
128
 
@@ -131,9 +138,13 @@ module Rosemary
131
138
  #
132
139
  def find_element(type, id)
133
140
  raise ArgumentError.new("type needs to be one of 'node', 'way', and 'relation'") unless type =~ /^(node|way|relation|changeset)$/
134
- raise TypeError.new('id needs to be a positive integer') unless(id.kind_of?(Fixnum) && id > 0)
135
- response = get("/#{type}/#{id}")
136
- response.is_a?(Array ) ? response.first : response
141
+ return nil if id.nil?
142
+ begin
143
+ response = get("/#{type}/#{id}")
144
+ response.is_a?(Array ) ? response.first : response
145
+ rescue NotFound
146
+ nil
147
+ end
137
148
  end
138
149
 
139
150
  private
@@ -197,14 +208,6 @@ module Rosemary
197
208
  end
198
209
  end
199
210
 
200
- def find_open_changeset
201
- find_changesets_for_user(:open => true).first
202
- end
203
-
204
- def find_or_create_open_changeset(options = {})
205
- @changeset = (find_open_changeset || create_changeset)
206
- end
207
-
208
211
  def check_response_codes(response)
209
212
  body = response.body
210
213
  case response.code.to_i
@@ -220,7 +223,7 @@ module Rosemary
220
223
  # when 414 then raise UriTooLarge.new(body)
221
224
  when 500 then raise ServerError
222
225
  when 503 then raise Unavailable.new('Service Unavailable')
223
- else raise Error("Unknown response code: #{response.code}")
226
+ else raise "Unknown response code: #{response.code}"
224
227
  end
225
228
  end
226
229
 
@@ -30,19 +30,20 @@ module Rosemary
30
30
  attr_reader :tags
31
31
 
32
32
  def initialize(attrs = {}) #:nodoc:
33
- attrs.stringify_keys!
34
- @id = attrs['id'].to_i if attrs['id']
35
- @uid = attrs['uid'].to_i
36
- @user = attrs['user']
37
- @created_at = Time.parse(attrs['created_at']) rescue nil
38
- @closed_at = Time.parse(attrs['closed_at']) rescue nil
39
- @open = attrs['open']
40
- @tags = Tags.new
41
- @tags[:created_by] = 'osm for ruby'
42
- @min_lat = attrs['min_lat'].to_f
43
- @min_lon = attrs['min_lon'].to_f
44
- @max_lat = attrs['max_lat'].to_f
45
- @max_lon = attrs['max_lon'].to_f
33
+ attrs = attrs.dup.stringify_keys!
34
+ @id = attrs['id'].to_i if attrs['id']
35
+ @uid = attrs['uid'].to_i
36
+ @user = attrs['user']
37
+ @created_at = Time.parse(attrs['created_at']) rescue nil
38
+ @closed_at = Time.parse(attrs['closed_at']) rescue nil
39
+ @open = attrs['open']
40
+ tags = attrs['tags'] || {}
41
+ @tags = Tags.new.merge(tags.dup.stringify_keys!)
42
+ @tags['created_by'] = 'osm for ruby'
43
+ @min_lat = attrs['min_lat'].to_f
44
+ @min_lon = attrs['min_lon'].to_f
45
+ @max_lat = attrs['max_lat'].to_f
46
+ @max_lon = attrs['max_lon'].to_f
46
47
 
47
48
  end
48
49
 
@@ -12,9 +12,6 @@ module Rosemary
12
12
  # This error occurs when Rosemary is instantiated without a client
13
13
  class CredentialsMissing < StandardError; end
14
14
 
15
- # This error occurs when Rosemary has no changeset.
16
- class ChangesetMissing < StandardError; end
17
-
18
15
  # An object was not found in the database.
19
16
  class NotFound < Error; end
20
17
 
@@ -1,3 +1,3 @@
1
1
  module Rosemary
2
- VERSION = "0.2.8"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/rosemary.rb CHANGED
@@ -2,7 +2,6 @@ require "rosemary/version"
2
2
 
3
3
  require 'hash'
4
4
  require 'active_model'
5
- require 'changeset_callbacks'
6
5
  require 'rosemary/tags'
7
6
  require 'rosemary/element'
8
7
  require 'rosemary/node'
data/rosemary.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.date = "2012-03-22"
12
12
  s.description = "OpenStreetMap API client for ruby"
13
13
  s.email = ["info@christophbuente.de"]
14
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "lib/changeset_callbacks.rb", "lib/hash.rb", "lib/rosemary/api.rb", "lib/rosemary/basic_auth_client.rb", "lib/rosemary/changeset.rb", "lib/rosemary/element.rb", "lib/rosemary/errors.rb", "lib/rosemary/member.rb", "lib/rosemary/node.rb", "lib/rosemary/oauth_client.rb", "lib/rosemary/parser.rb", "lib/rosemary/relation.rb", "lib/rosemary/tags.rb", "lib/rosemary/user.rb", "lib/rosemary/way.rb", "lib/rosemary.rb"]
14
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md"]
15
15
  s.homepage = "https://github.com/sozialhelden/rosemary"
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "OpenStreetMap", "--main", "README.md"]
17
17
  s.require_paths = ["lib"]
@@ -1,13 +1,18 @@
1
1
  require 'spec_helper'
2
+ include Rosemary
2
3
 
3
- describe Rosemary::Changeset do
4
+ describe Changeset do
4
5
 
5
6
  before do
6
7
  WebMock.disable_net_connect!
7
8
  end
8
9
 
9
10
  let :osm do
10
- Rosemary::Api.new
11
+ Api.new
12
+ end
13
+
14
+ let :auth_osm do
15
+ Api.new(BasicAuthClient.new('a_username', 'a_password'))
11
16
  end
12
17
 
13
18
  def valid_fake_user
@@ -61,11 +66,11 @@ describe Rosemary::Changeset do
61
66
 
62
67
  describe '#find:' do
63
68
 
64
- let :request_url do
69
+ def request_url
65
70
  "http://www.openstreetmap.org/api/0.6/changeset/10"
66
71
  end
67
72
 
68
- let :stubbed_request do
73
+ def stubbed_request
69
74
  stub_request(:get, request_url)
70
75
  end
71
76
 
@@ -73,28 +78,63 @@ describe Rosemary::Changeset do
73
78
  stubbed_request.to_return(:status => 200, :body => single_changeset, :headers => {'Content-Type' => 'application/xml'})
74
79
  changeset = osm.find_changeset(10)
75
80
  assert_requested :get, request_url, :times => 1
76
- changeset.class.should eql Rosemary::Changeset
81
+ changeset.class.should eql Changeset
77
82
  end
78
83
 
79
84
  it "should raise an NotFound error, when a changeset cannot be found" do
80
85
  stubbed_request.to_return(:status => 404, :body => '', :headers => {'Content-Type' => 'text/plain'})
81
- lambda {
82
- node = osm.find_changeset(10)
83
- }.should raise_error(Rosemary::NotFound)
86
+ node = osm.find_changeset(10)
87
+ node.should be_nil
84
88
  end
85
89
  end
86
90
 
87
- describe '#find_for_user' do
91
+ describe '#create' do
92
+
93
+ def request_url
94
+ "http://a_username:a_password@www.openstreetmap.org/api/0.6/changeset/create"
95
+ end
88
96
 
89
- let :osm do
90
- Rosemary::Api.new(Rosemary::BasicAuthClient.new('a_username', 'a_password'))
97
+ def stub_create_request
98
+ stub_request(:put, request_url)
91
99
  end
92
100
 
93
- let :request_url do
101
+ it "should post a new changeset with given comment" do
102
+ body = Changeset.new(:tags => { :comment => 'New changeset' }).to_xml
103
+
104
+ stub_create_request.with(:body => body).to_return(:status => 200, :body => "3", :headers => {'Content-Type' => 'plain/text'})
105
+ auth_osm.should_receive(:find_changeset).with(3).and_return(cs = mock())
106
+ auth_osm.create_changeset('New changeset').should == cs
107
+ end
108
+ end
109
+
110
+ describe "#find_or_create_open_changeset" do
111
+ it "returns an exisiting changeset if that exists and is open" do
112
+ auth_osm.should_receive(:find_changeset).with(3).and_return(cs = mock(:open? => true))
113
+ auth_osm.should_not_receive(:create_changeset)
114
+ auth_osm.find_or_create_open_changeset(3, "some foo comment").should == cs
115
+ end
116
+
117
+ it "returns an new changeset if the requested one exists and is closed" do
118
+ auth_osm.should_receive(:find_changeset).with(3).and_return(mock(:open? => false))
119
+ auth_osm.should_receive(:create_changeset).with("some foo comment").and_return(cs = mock())
120
+ auth_osm.find_or_create_open_changeset(3, "some foo comment").should == cs
121
+ end
122
+
123
+ it "returns an new changeset if the requested one doesn't exist" do
124
+ auth_osm.should_receive(:find_changeset).with(3).and_return(nil)
125
+ auth_osm.should_receive(:create_changeset).with("some foo comment").and_return(cs = mock())
126
+ auth_osm.find_or_create_open_changeset(3, "some foo comment").should == cs
127
+ end
128
+
129
+ end
130
+
131
+ describe '#find_for_user' do
132
+
133
+ def request_url
94
134
  "http://www.openstreetmap.org/api/0.6/changesets?user=1234"
95
135
  end
96
136
 
97
- let :stubbed_request do
137
+ def stubbed_request
98
138
  stub_request(:get, request_url)
99
139
  end
100
140
 
@@ -104,22 +144,22 @@ describe Rosemary::Changeset do
104
144
 
105
145
  it "should not find changeset for user if user has none" do
106
146
  stubbed_request.to_return(:status => 200, :body => missing_changeset, :headers => {'Content-Type' => 'application/xml'})
107
- changesets = osm.find_changesets_for_user
147
+ changesets = auth_osm.find_changesets_for_user
108
148
  changesets.should be_empty
109
149
  end
110
150
 
111
151
  it "should find a single changeset for user" do
112
152
  stubbed_request.to_return(:status => 200, :body => single_changeset, :headers => {'Content-Type' => 'application/xml'})
113
- changesets = osm.find_changesets_for_user
153
+ changesets = auth_osm.find_changesets_for_user
114
154
  changesets.size.should eql 1
115
- changesets.first.class.should eql Rosemary::Changeset
155
+ changesets.first.class.should eql Changeset
116
156
  end
117
157
 
118
158
  it "should find a multiple changesets for a user" do
119
159
  stubbed_request.to_return(:status => 200, :body => multiple_changeset, :headers => {'Content-Type' => 'application/xml'})
120
- changesets = osm.find_changesets_for_user
160
+ changesets = auth_osm.find_changesets_for_user
121
161
  changesets.size.should eql 2
122
- changesets.first.class.should eql Rosemary::Changeset
162
+ changesets.first.class.should eql Changeset
123
163
  end
124
164
  end
125
165
 
@@ -1,20 +1,20 @@
1
1
  require 'spec_helper'
2
-
3
- describe Rosemary::Node do
2
+ include Rosemary
3
+ describe Node do
4
4
 
5
5
  before do
6
6
  WebMock.disable_net_connect!
7
7
  end
8
8
 
9
- let :osm do
10
- Rosemary::Api.new
11
- end
9
+ let(:changeset) { Changeset.new(:id => 1) }
12
10
 
13
- let :stub_changeset_lookup do
11
+ let(:osm) { Api.new }
12
+
13
+ def stub_changeset_lookup
14
14
  stub_request(:get, "http://www.openstreetmap.org/api/0.6/changesets?open=true&user=1234").to_return(:status => 200, :body => valid_fake_changeset, :headers => {'Content-Type' => 'application/xml'} )
15
15
  end
16
16
 
17
- let :stub_node_lookup do
17
+ def stub_node_lookup
18
18
  stub_request(:get, "http://www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => valid_fake_node, :headers => {'Content-Type' => 'application/xml'})
19
19
  end
20
20
 
@@ -60,11 +60,11 @@ describe Rosemary::Node do
60
60
 
61
61
  describe '#find:' do
62
62
 
63
- let :request_url do
63
+ def request_url
64
64
  "http://www.openstreetmap.org/api/0.6/node/1234"
65
65
  end
66
66
 
67
- let :stubbed_request do
67
+ def stubbed_request
68
68
  stub_request(:get, request_url)
69
69
  end
70
70
 
@@ -72,7 +72,7 @@ describe Rosemary::Node do
72
72
  stubbed_request.to_return(:status => 200, :body => valid_fake_node, :headers => {'Content-Type' => 'application/xml'})
73
73
  node = osm.find_node 1234
74
74
  assert_requested :get, request_url, :times => 1
75
- node.class.should eql Rosemary::Node
75
+ node.class.should eql Node
76
76
  node.tags.size.should eql 3
77
77
  node.tags['name'].should eql 'The rose'
78
78
  node['name'].should eql 'The rose'
@@ -84,84 +84,95 @@ describe Rosemary::Node do
84
84
  stubbed_request.to_timeout
85
85
  lambda {
86
86
  node = osm.find_node(1234)
87
- }.should raise_error(Rosemary::Unavailable)
87
+ }.should raise_error(Unavailable)
88
88
  end
89
89
 
90
90
  it "should raise an Gone error, when a node has been deleted" do
91
91
  stubbed_request.to_return(:status => 410, :body => '', :headers => {'Content-Type' => 'text/plain'})
92
92
  lambda {
93
93
  node = osm.find_node(1234)
94
- }.should raise_error(Rosemary::Gone)
94
+ }.should raise_error(Gone)
95
95
  end
96
96
 
97
97
  it "should raise an NotFound error, when a node cannot be found" do
98
98
  stubbed_request.to_return(:status => 404, :body => '', :headers => {'Content-Type' => 'text/plain'})
99
- lambda {
100
- node = osm.find_node(1234)
101
- }.should raise_error(Rosemary::NotFound)
99
+ node = osm.find_node(1234)
100
+ node.should be_nil
102
101
  end
103
102
  end
104
103
 
105
104
  describe 'with BasicAuthClient' do
106
105
 
107
106
  let :osm do
108
- Rosemary::Api.new(Rosemary::BasicAuthClient.new('a_username', 'a_password'))
107
+ Api.new(BasicAuthClient.new('a_username', 'a_password'))
109
108
  end
110
109
 
111
- let :stub_user_lookup do
110
+ def stub_user_lookup
112
111
  stub_request(:get, "http://a_username:a_password@www.openstreetmap.org/api/0.6/user/details").to_return(:status => 200, :body => valid_fake_user, :headers => {'Content-Type' => 'application/xml'} )
113
112
  end
114
113
 
115
114
  describe '#create:' do
116
115
 
117
- let (:node) { Rosemary::Node.new }
118
- let (:request_url) { "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/create" }
119
- let (:stubbed_request) { stub_request(:put, request_url) }
116
+ let (:node) { Node.new }
117
+
118
+ let (:expected_body) {
119
+ expected_node = node.dup
120
+ expected_node.changeset = changeset.id
121
+ expected_node.to_xml
122
+ }
123
+
124
+ def request_url
125
+ "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/create"
126
+ end
127
+
128
+ def stubbed_request
129
+ stub_request(:put, request_url)
130
+ end
120
131
 
121
132
  before do
122
- stub_changeset_lookup
123
133
  stub_user_lookup
124
134
  end
125
135
 
126
136
  it "should create a new Node from given attributes" do
127
- stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
128
- node.id.should be_nil
129
- new_id = osm.save(node)
137
+ stubbed_request.with(:body => expected_body).
138
+ to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
139
+
140
+ new_id = osm.create(node, changeset)
130
141
  end
131
142
 
132
143
  it "should raise a Unavailable, when api times out" do
133
144
  stubbed_request.to_timeout
134
145
  lambda {
135
- new_id = osm.save(node)
136
- }.should raise_error(Rosemary::Unavailable)
146
+ new_id = osm.create(node, changeset)
147
+ }.should raise_error(Unavailable)
137
148
  end
138
149
 
139
150
  it "should not create a Node with invalid xml but raise BadRequest" do
140
151
  stubbed_request.to_return(:status => 400, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
141
152
  lambda {
142
- new_id = osm.save(node)
143
- }.should raise_error(Rosemary::BadRequest)
153
+ new_id = osm.save(node, changeset)
154
+ }.should raise_error(BadRequest)
144
155
  end
145
156
 
146
157
  it "should not allow to create a node when a changeset has been closed" do
147
158
  stubbed_request.to_return(:status => 409, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
148
159
  lambda {
149
- new_id = osm.save(node)
150
- }.should raise_error(Rosemary::Conflict)
160
+ new_id = osm.save(node, changeset)
161
+ }.should raise_error(Conflict)
151
162
  end
152
163
 
153
164
  it "should not allow to create a node when no authentication client is given" do
154
- osm = Rosemary::Api.new
165
+ osm = Api.new
155
166
  lambda {
156
- osm.save(node)
157
- }.should raise_error(Rosemary::CredentialsMissing)
167
+ osm.save(node, changeset)
168
+ }.should raise_error(CredentialsMissing)
158
169
  end
159
170
 
160
171
  it "should set a changeset" do
161
172
  stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
162
173
  node.changeset = nil
163
- osm.save(node)
164
- node.changeset.should == osm.changeset.id
174
+ osm.save(node, changeset)
175
+ node.changeset.should == changeset.id
165
176
  end
166
177
  end
167
178
 
@@ -172,7 +183,6 @@ describe Rosemary::Node do
172
183
  end
173
184
 
174
185
  before do
175
- stub_changeset_lookup
176
186
  stub_user_lookup
177
187
  stub_node_lookup
178
188
  end
@@ -182,15 +192,15 @@ describe Rosemary::Node do
182
192
  node.tags['amenity'] = 'restaurant'
183
193
  node.tags['name'] = 'Il Tramonto'
184
194
  node.should_receive(:changeset=)
185
- new_version = osm.save(node)
195
+ new_version = osm.save(node, changeset)
186
196
  new_version.should eql 43
187
197
  end
188
198
 
189
199
  it "should set a changeset" do
190
200
  stub_request(:put, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
191
201
  node.changeset = nil
192
- osm.save(node)
193
- node.changeset.should == osm.changeset.id
202
+ osm.save(node, changeset)
203
+ node.changeset.should == changeset.id
194
204
  end
195
205
 
196
206
 
@@ -209,62 +219,62 @@ describe Rosemary::Node do
209
219
  end
210
220
 
211
221
  it "should not delete an node with missing id" do
212
- node = Rosemary::Node.new
213
- osm.destroy(node)
222
+ node = Node.new
223
+ osm.destroy(node, changeset)
214
224
  end
215
225
 
216
226
  it "should delete an existing node" do
217
227
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
218
228
  node.should_receive(:changeset=)
219
- new_version = osm.destroy(node)
229
+ new_version = osm.destroy(node, changeset)
220
230
  new_version.should eql 43 # new version number
221
231
  end
222
232
 
223
233
  it "should raise an error if node to be deleted is still part of a way" do
224
234
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 400, :body => 'Version does not match current database version', :headers => {'Content-Type' => 'text/plain'})
225
235
  lambda {
226
- response = osm.destroy(node)
236
+ response = osm.destroy(node, changeset)
227
237
  response.should eql "Version does not match current database version"
228
- }.should raise_error Rosemary::BadRequest
238
+ }.should raise_error BadRequest
229
239
  end
230
240
 
231
241
  it "should raise an error if node cannot be found" do
232
242
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 404, :body => 'Node cannot be found', :headers => {'Content-Type' => 'text/plain'})
233
243
  lambda {
234
- response = osm.destroy(node)
244
+ response = osm.destroy(node, changeset)
235
245
  response.should eql "Node cannot be found"
236
- }.should raise_error Rosemary::NotFound
246
+ }.should raise_error NotFound
237
247
  end
238
248
 
239
249
  it "should raise an error if there is a conflict" do
240
250
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 409, :body => 'Node has been deleted in this changeset', :headers => {'Content-Type' => 'text/plain'})
241
251
  lambda {
242
- response = osm.destroy(node)
252
+ response = osm.destroy(node, changeset)
243
253
  response.should eql "Node has been deleted in this changeset"
244
- }.should raise_error Rosemary::Conflict
254
+ }.should raise_error Conflict
245
255
  end
246
256
 
247
257
  it "should raise an error if the node is already delted" do
248
258
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 410, :body => 'Node has been deleted', :headers => {'Content-Type' => 'text/plain'})
249
259
  lambda {
250
- response = osm.destroy(node)
260
+ response = osm.destroy(node, changeset)
251
261
  response.should eql "Node has been deleted"
252
- }.should raise_error Rosemary::Gone
262
+ }.should raise_error Gone
253
263
  end
254
264
 
255
265
  it "should raise an error if the node is part of a way" do
256
266
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 412, :body => 'Node 123 is still used by way 456', :headers => {'Content-Type' => 'text/plain'})
257
267
  lambda {
258
- response = osm.destroy(node)
268
+ response = osm.destroy(node, changeset)
259
269
  response.should eql "Node 123 is still used by way 456"
260
- }.should raise_error Rosemary::Precondition
270
+ }.should raise_error Precondition
261
271
  end
262
272
 
263
273
  it "should set the changeset an existing node" do
264
274
  stub_request(:delete, "http://a_username:a_password@www.openstreetmap.org/api/0.6/node/123").to_return(:status => 200, :body => '43', :headers => {'Content-Type' => 'text/plain'})
265
275
  node.changeset = nil
266
- new_version = osm.destroy(node)
267
- node.changeset.should == osm.changeset.id
276
+ new_version = osm.destroy(node, changeset)
277
+ node.changeset.should == changeset.id
268
278
  end
269
279
  end
270
280
  end
@@ -287,23 +297,23 @@ describe Rosemary::Node do
287
297
  end
288
298
 
289
299
  let :osm do
290
- Rosemary::Api.new(Rosemary::OauthClient.new(access_token))
300
+ Api.new(OauthClient.new(access_token))
291
301
  end
292
302
 
293
- let :stub_user_lookup do
303
+ def stub_user_lookup
294
304
  stub_request(:get, "http://www.openstreetmap.org/api/0.6/user/details").to_return(:status => 200, :body => valid_fake_user, :headers => {'Content-Type' => 'application/xml'} )
295
305
  end
296
306
 
297
307
  describe '#create:' do
298
308
  let :node do
299
- Rosemary::Node.new
309
+ Node.new
300
310
  end
301
311
 
302
- let :request_url do
312
+ def request_url
303
313
  "http://www.openstreetmap.org/api/0.6/node/create"
304
314
  end
305
315
 
306
- let :stubbed_request do
316
+ def stubbed_request
307
317
  stub_request(:put, request_url)
308
318
  end
309
319
 
@@ -315,36 +325,36 @@ describe Rosemary::Node do
315
325
  it "should create a new Node from given attributes" do
316
326
  stubbed_request.to_return(:status => 200, :body => '123', :headers => {'Content-Type' => 'text/plain'})
317
327
  node.id.should be_nil
318
- new_id = osm.save(node)
328
+ new_id = osm.save(node, changeset)
319
329
  end
320
330
 
321
331
  it "should raise a Unavailable, when api times out" do
322
332
  stubbed_request.to_timeout
323
333
  lambda {
324
- new_id = osm.save(node)
325
- }.should raise_error(Rosemary::Unavailable)
334
+ new_id = osm.save(node, changeset)
335
+ }.should raise_error(Unavailable)
326
336
  end
327
337
 
328
338
 
329
339
  it "should not create a Node with invalid xml but raise BadRequest" do
330
340
  stubbed_request.to_return(:status => 400, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
331
341
  lambda {
332
- new_id = osm.save(node)
333
- }.should raise_error(Rosemary::BadRequest)
342
+ new_id = osm.save(node, changeset)
343
+ }.should raise_error(BadRequest)
334
344
  end
335
345
 
336
346
  it "should not allow to create a node when a changeset has been closed" do
337
347
  stubbed_request.to_return(:status => 409, :body => 'The given node is invalid', :headers => {'Content-Type' => 'text/plain'})
338
348
  lambda {
339
- new_id = osm.save(node)
340
- }.should raise_error(Rosemary::Conflict)
349
+ new_id = osm.save(node, changeset)
350
+ }.should raise_error(Conflict)
341
351
  end
342
352
 
343
353
  it "should not allow to create a node when no authentication client is given" do
344
- osm = Rosemary::Api.new
354
+ osm = Api.new
345
355
  lambda {
346
- osm.save(node)
347
- }.should raise_error(Rosemary::CredentialsMissing)
356
+ osm.save(node, changeset)
357
+ }.should raise_error(CredentialsMissing)
348
358
  end
349
359
 
350
360
  end
@@ -366,7 +376,7 @@ describe Rosemary::Node do
366
376
  node.tags['amenity'] = 'restaurant'
367
377
  node.tags['name'] = 'Il Tramonto'
368
378
  node.should_receive(:changeset=)
369
- new_version = osm.save(node)
379
+ new_version = osm.save(node, changeset)
370
380
  new_version.should eql 43
371
381
  end
372
382
  end
@@ -388,8 +398,8 @@ describe Rosemary::Node do
388
398
  node.should_receive(:changeset=)
389
399
  lambda {
390
400
  # Delete is not implemented using oauth
391
- new_version = osm.destroy(node)
392
- }.should raise_error(Rosemary::NotImplemented)
401
+ new_version = osm.destroy(node, changeset)
402
+ }.should raise_error(NotImplemented)
393
403
  end
394
404
  end
395
405
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
-
3
- describe Rosemary::User do
2
+ include Rosemary
3
+ describe User do
4
4
 
5
5
  before do
6
6
  WebMock.disable_net_connect!
@@ -22,7 +22,7 @@ describe Rosemary::User do
22
22
  end
23
23
 
24
24
  let :osm do
25
- Rosemary::Api.new(Rosemary::OauthClient.new(access_token))
25
+ Api.new(OauthClient.new(access_token))
26
26
  end
27
27
 
28
28
  def valid_fake_user
@@ -47,14 +47,14 @@ describe Rosemary::User do
47
47
  it "should build a User from API response via find_user" do
48
48
  stub_request(:get, "http://www.openstreetmap.org/api/0.6/user/details").to_return(:status => 200, :body => valid_fake_user, :headers => {'Content-Type' => 'application/xml'})
49
49
  user = osm.find_user
50
- user.class.should eql Rosemary::User
50
+ user.class.should eql User
51
51
  end
52
52
 
53
53
  it "should raise error from api" do
54
54
  stub_request(:get, "http://www.openstreetmap.org/api/0.6/user/details").to_return(:status => 403, :body => "OAuth token doesn't have that capability.", :headers => {'Content-Type' => 'plain/text'})
55
55
  lambda {
56
56
  osm.find_user
57
- }.should raise_error Rosemary::Forbidden
57
+ }.should raise_error Forbidden
58
58
  end
59
59
  end
60
60
  end
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
-
3
- describe Rosemary::Way do
2
+ include Rosemary
3
+ describe Way do
4
4
 
5
5
  before do
6
6
  WebMock.disable_net_connect!
7
7
  end
8
8
 
9
9
  let :osm do
10
- Rosemary::Api.new
10
+ Api.new
11
11
  end
12
12
 
13
13
  def valid_fake_way
@@ -36,7 +36,7 @@ describe Rosemary::Way do
36
36
  it "should build a Way from API response via get_way" do
37
37
  stub_request(:get, "http://www.openstreetmap.org/api/0.6/way/1234").to_return(:status => 200, :body => valid_fake_way, :headers => {'Content-Type' => 'application/xml'})
38
38
  way = osm.find_way(1234)
39
- way.class.should eql Rosemary::Way
39
+ way.class.should eql Way
40
40
  way.nodes.should include(15735246)
41
41
  end
42
42
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
-
3
- describe 'Rosemary::Changeset' do
2
+ include Rosemary
3
+ describe Changeset do
4
4
 
5
5
  let :changeset do
6
- Rosemary::Changeset.new( :id => "123",
6
+ Changeset.new( :id => "123",
7
7
  :user => "fred",
8
8
  :uid => "123",
9
9
  :created_at => "2008-11-08T19:07:39+01:00",
@@ -11,80 +11,98 @@ describe 'Rosemary::Changeset' do
11
11
  :min_lat => "52.2",
12
12
  :max_lat => "52.3",
13
13
  :min_lon => "13.4",
14
- :max_lon => "13.5")
14
+ :max_lon => "13.5",
15
+ :tags => { :comment => 'A bloody comment' })
15
16
  end
16
17
 
17
- it "should have an id attribute set from attributes" do
18
- changeset.id.should eql(123)
19
- end
18
+ context 'attributes' do
20
19
 
21
- it "should have an id attribute within xml representation" do
22
- changeset.to_xml.should match /id=\"123\"/
23
- end
20
+ subject { changeset }
24
21
 
25
- it "should have a user attributes set from attributes" do
26
- changeset.user.should eql("fred")
27
- end
22
+ it "should have an id attribute set from attributes" do
23
+ subject.id.should eql(123)
24
+ end
28
25
 
29
- it "should have a user attribute within xml representation" do
30
- changeset.to_xml.should match /user=\"fred\"/
31
- end
26
+ it "should have a user attributes set from attributes" do
27
+ subject.user.should eql("fred")
28
+ end
32
29
 
33
- it "should have an uid attribute set from attributes" do
34
- changeset.uid.should eql(123)
35
- end
30
+ it "should have an uid attribute set from attributes" do
31
+ subject.uid.should eql(123)
32
+ end
36
33
 
37
- it "should have an uid attribute within xml representation" do
38
- changeset.to_xml.should match /uid=\"123\"/
39
- end
34
+ it "should have a changeset attributes set from attributes" do
35
+ subject.should be_open
36
+ end
40
37
 
41
- it "should have a changeset attributes set from attributes" do
42
- changeset.should be_open
43
- end
38
+ it "should have a min_lat attribute set from attributes" do
39
+ subject.min_lat.should eql(52.2)
40
+ end
44
41
 
45
- it "should have an open attribute within xml representation" do
46
- changeset.to_xml.should match /open=\"true\"/
47
- end
42
+ it "should have a min_lon attribute set from attributes" do
43
+ subject.min_lon.should eql(13.4)
44
+ end
48
45
 
49
- it "should have a min_lat attribute set from attributes" do
50
- changeset.min_lat.should eql(52.2)
51
- end
46
+ it "should have a max_lat attribute set from attributes" do
47
+ subject.max_lat.should eql(52.3)
48
+ end
52
49
 
53
- it "should have a min_lat attribute within xml representation" do
54
- changeset.to_xml.should match /min_lat=\"52.2\"/
55
- end
50
+ it "should have a max_lon attribute set from attributes" do
51
+ subject.max_lon.should eql(13.5)
52
+ end
56
53
 
57
- it "should have a min_lon attribute set from attributes" do
58
- changeset.min_lon.should eql(13.4)
59
- end
54
+ it "should have a created_at attribute set from attributes" do
55
+ subject.created_at.should eql Time.parse('2008-11-08T19:07:39+01:00')
56
+ end
60
57
 
61
- it "should have a min_lon attribute within xml representation" do
62
- changeset.to_xml.should match /min_lon=\"13.4\"/
58
+ it "should have a comment attribute set from attributes" do
59
+ subject.tags['comment'].should eql 'A bloody comment'
60
+ end
63
61
  end
64
62
 
65
- it "should have a max_lat attribute set from attributes" do
66
- changeset.max_lat.should eql(52.3)
67
- end
63
+ context 'xml representation' do
68
64
 
69
- it "should have a max_lat attribute within xml representation" do
70
- changeset.to_xml.should match /max_lat=\"52.3\"/
71
- end
65
+ subject { changeset.to_xml }
72
66
 
73
- it "should have a max_lon attribute set from attributes" do
74
- changeset.max_lon.should eql(13.5)
75
- end
67
+ it "should have an id attribute within xml representation" do
68
+ subject.should have_xml "//changeset[@id='123']"
69
+ end
76
70
 
77
- it "should have a max_lon attribute within xml representation" do
78
- changeset.to_xml.should match /max_lon=\"13.5\"/
79
- end
71
+ it "should have a user attribute within xml representation" do
72
+ subject.should have_xml "//changeset[@user='fred']"
73
+ end
80
74
 
81
- it "should have a created_at attribute set from attributes" do
82
- changeset.created_at.should eql Time.parse('2008-11-08T19:07:39+01:00')
83
- end
75
+ it "should have an uid attribute within xml representation" do
76
+ subject.should have_xml "//changeset[@uid='123']"
77
+ end
84
78
 
85
- it "should have a created_at attribute within xml representation" do
86
- changeset.to_xml.should match /created_at=\"/
87
- end
79
+ it "should have an open attribute within xml representation" do
80
+ subject.should have_xml "//changeset[@open='true']"
81
+ end
88
82
 
83
+ it "should have a min_lat attribute within xml representation" do
84
+ subject.should have_xml "//changeset[@min_lat='52.2']"
85
+ end
89
86
 
87
+ it "should have a min_lon attribute within xml representation" do
88
+ subject.should have_xml "//changeset[@min_lon='13.4']"
89
+ end
90
+
91
+ it "should have a max_lat attribute within xml representation" do
92
+ subject.should have_xml "//changeset[@max_lat='52.3']"
93
+ end
94
+
95
+ it "should have a max_lon attribute within xml representation" do
96
+ subject.should have_xml "//changeset[@max_lon='13.5']"
97
+ end
98
+
99
+ it "should have a created_at attribute within xml representation" do
100
+ subject.should have_xml "//changeset[@created_at='2008-11-08 19:07:39 +0100']"
101
+ end
102
+
103
+ it "should have a comment tag within xml representation" do
104
+ subject.should have_xml "//tag[@k='comment'][@v='A bloody comment']"
105
+ end
106
+
107
+ end
90
108
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
-
3
- describe 'Rosemary::Node' do
2
+ describe Rosemary
3
+ describe Node do
4
4
 
5
5
  subject do
6
- Rosemary::Node.new(:id => "123",
6
+ Node.new(:id => "123",
7
7
  :lat => "52.2",
8
8
  :lon => "13.4",
9
9
  :changeset => "12",
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
-
3
- describe 'Rosemary::Relation' do
2
+ include Rosemary
3
+ describe Relation do
4
4
 
5
5
  subject do
6
- Rosemary::Relation.new(:id => "123",
6
+ Relation.new(:id => "123",
7
7
  :lat => "52.2",
8
8
  :lon => "13.4",
9
9
  :changeset => "12",
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
-
3
- describe 'Rosemary::Way' do
2
+ include Rosemary
3
+ describe Way do
4
4
 
5
5
  def valid_fake_way
6
6
  way=<<-EOF
@@ -24,7 +24,7 @@ describe 'Rosemary::Way' do
24
24
  end
25
25
 
26
26
  subject do
27
- @way ||= Rosemary::Way.from_xml(valid_fake_way)
27
+ @way ||= Way.from_xml(valid_fake_way)
28
28
  end
29
29
 
30
30
  it "should have 4 nodes" do
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,31 @@
1
1
  require 'webmock/rspec'
2
2
  require 'rosemary'
3
3
 
4
+ require 'libxml'
5
+
6
+ RSpec::Matchers.define :have_xml do |xpath, text|
7
+ match do |body|
8
+ parser = LibXML::XML::Parser.string body
9
+ doc = parser.parse
10
+ nodes = doc.find(xpath)
11
+ nodes.empty?.should be_false
12
+ if text
13
+ nodes.each do |node|
14
+ node.content.should == text
15
+ end
16
+ end
17
+ true
18
+ end
19
+
20
+ failure_message_for_should do |body|
21
+ "expected to find xml tag #{xpath} in:\n#{body}"
22
+ end
23
+
24
+ failure_message_for_should_not do |response|
25
+ "expected not to find xml tag #{xpath} in:\n#{body}"
26
+ end
27
+
28
+ description do
29
+ "have xml tag #{xpath}"
30
+ end
31
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rosemary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-03-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
16
- requirement: &70147855734540 !ruby/object:Gem::Requirement
16
+ requirement: &70283461963940 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70147855734540
24
+ version_requirements: *70283461963940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: libxml-ruby
27
- requirement: &70147855733880 !ruby/object:Gem::Requirement
27
+ requirement: &70283461963320 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70147855733880
35
+ version_requirements: *70283461963320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: builder
38
- requirement: &70147855733360 !ruby/object:Gem::Requirement
38
+ requirement: &70283461962620 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70147855733360
46
+ version_requirements: *70283461962620
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: oauth
49
- requirement: &70147855732860 !ruby/object:Gem::Requirement
49
+ requirement: &70283461961580 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70147855732860
57
+ version_requirements: *70283461961580
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: activemodel
60
- requirement: &70147855732360 !ruby/object:Gem::Requirement
60
+ requirement: &70283461961100 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70147855732360
68
+ version_requirements: *70283461961100
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70147855731880 !ruby/object:Gem::Requirement
71
+ requirement: &70283461960400 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70147855731880
79
+ version_requirements: *70283461960400
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: webmock
82
- requirement: &70147855731400 !ruby/object:Gem::Requirement
82
+ requirement: &70283461959920 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70147855731400
90
+ version_requirements: *70283461959920
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rake
93
- requirement: &70147855730900 !ruby/object:Gem::Requirement
93
+ requirement: &70283461959420 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70147855730900
101
+ version_requirements: *70283461959420
102
102
  description: OpenStreetMap API client for ruby
103
103
  email:
104
104
  - info@christophbuente.de
@@ -108,22 +108,6 @@ extra_rdoc_files:
108
108
  - CHANGELOG
109
109
  - LICENSE
110
110
  - README.md
111
- - lib/changeset_callbacks.rb
112
- - lib/hash.rb
113
- - lib/rosemary/api.rb
114
- - lib/rosemary/basic_auth_client.rb
115
- - lib/rosemary/changeset.rb
116
- - lib/rosemary/element.rb
117
- - lib/rosemary/errors.rb
118
- - lib/rosemary/member.rb
119
- - lib/rosemary/node.rb
120
- - lib/rosemary/oauth_client.rb
121
- - lib/rosemary/parser.rb
122
- - lib/rosemary/relation.rb
123
- - lib/rosemary/tags.rb
124
- - lib/rosemary/user.rb
125
- - lib/rosemary/way.rb
126
- - lib/rosemary.rb
127
111
  files:
128
112
  - .gitignore
129
113
  - .rbenv-version
@@ -136,7 +120,6 @@ files:
136
120
  - Manifest
137
121
  - README.md
138
122
  - Rakefile
139
- - lib/changeset_callbacks.rb
140
123
  - lib/hash.rb
141
124
  - lib/rosemary.rb
142
125
  - lib/rosemary/api.rb
@@ -183,7 +166,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
166
  version: '0'
184
167
  segments:
185
168
  - 0
186
- hash: -3755060652839665335
169
+ hash: 4264551617807260197
187
170
  required_rubygems_version: !ruby/object:Gem::Requirement
188
171
  none: false
189
172
  requirements:
@@ -1,31 +0,0 @@
1
- # According to the OSM API any changes made to the date need an open changeset which belongs to the user
2
- # executing the changes.
3
- # To keep the code simple the before_save method is included which makes sure and open
4
- module ChangesetCallbacks
5
-
6
- def self.included(into)
7
- into.instance_methods(false).select{|method_name| [:save, :create, :update, :destroy].include?(method_name.to_sym)}.each do |m|
8
- ChangesetCallbacks.before_write(into, m)
9
- end
10
-
11
- def into.method_added(m)
12
- unless @adding
13
- @adding = true
14
- if [:save, :create, :update, :destroy].include?(m.to_sym)
15
- ChangesetCallbacks.before_write(self, m)
16
- end
17
- @adding = false
18
- end
19
- end
20
- end
21
-
22
- def ChangesetCallbacks.before_write(klass, meth)
23
- klass.class_eval do
24
- alias_method "old_#{meth}", "#{meth}"
25
- define_method(meth) do |*args|
26
- find_or_create_open_changeset
27
- self.send("old_#{meth}", *args)
28
- end
29
- end
30
- end
31
- end