From bd50d82f701c55d89b891ebd216ec84008b486c1 Mon Sep 17 00:00:00 2001 From: Rick Olson Date: Sun, 29 Apr 2007 03:14:36 +0000 Subject: Add support for setting custom headers per ActiveResource model [Rick] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6624 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activeresource/CHANGELOG | 9 ++++++++ activeresource/lib/active_resource/base.rb | 14 +++++++----- activeresource/lib/active_resource/connection.rb | 20 ++++++++--------- .../lib/active_resource/custom_methods.rb | 18 ++++++++-------- activeresource/test/base_test.rb | 8 +++++++ activeresource/test/connection_test.rb | 25 ++++++++++++++++++++++ 6 files changed, 70 insertions(+), 24 deletions(-) diff --git a/activeresource/CHANGELOG b/activeresource/CHANGELOG index 403933f7aa..edee343db0 100644 --- a/activeresource/CHANGELOG +++ b/activeresource/CHANGELOG @@ -1,5 +1,14 @@ *SVN* +* Add support for setting custom headers per ActiveResource model [Rick] + + class Project + custom_headers['X-Token'] = 'foo' + end + + # makes the GET request with the custom X-Token header + Project.find(:all) + * Added find-by-path options to ActiveResource::Base.find [DHH]. Examples: employees = Person.find(:all, :from => "/companies/1/people.xml") # => GET /companies/1/people.xml diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index bcc1e8b497..5a2c54c5ec 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -29,6 +29,10 @@ module ActiveResource @connection end + def custom_headers + @custom_headers ||= {} + end + # Do not include any modules in the default element name. This makes it easier to seclude ARes objects # in a separate namespace without having to set element_name repeatedly. attr_accessor_with_default(:element_name) { to_s.split("::").last.underscore } #:nodoc: @@ -150,7 +154,7 @@ module ActiveResource prefix_options, query_options = split_options(options) from ||= collection_path(prefix_options, query_options) - instantiate_collection(connection.get(from) || []) + instantiate_collection(connection.get(from, custom_headers) || []) end def instantiate_collection(collection, prefix_options = {}) @@ -167,7 +171,7 @@ module ActiveResource prefix_options, query_options = split_options(options) from = scope.to_s.include?("/") ? scope : element_path(scope, prefix_options, query_options) - returning new(connection.get(from)) do |resource| + returning new(connection.get(from, custom_headers)) do |resource| resource.prefix_options = prefix_options end end @@ -254,7 +258,7 @@ module ActiveResource # Delete the resource. def destroy - connection.delete(element_path) + connection.delete(element_path, self.class.custom_headers) end # Evaluates to true if this resource is found. @@ -300,14 +304,14 @@ module ActiveResource # Update the resource on the remote service. def update - returning connection.put(element_path(prefix_options), to_xml) do |response| + returning connection.put(element_path(prefix_options), to_xml, self.class.custom_headers) do |response| load_attributes_from_response(response) end end # Create (i.e., save to the remote service) the new resource. def create - returning connection.post(collection_path, to_xml) do |response| + returning connection.post(collection_path, to_xml, self.class.custom_headers) do |response| self.id = id_from_response(response) load_attributes_from_response(response) end diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb index c37bb73834..bb3993512e 100644 --- a/activeresource/lib/active_resource/connection.rb +++ b/activeresource/lib/active_resource/connection.rb @@ -51,26 +51,26 @@ module ActiveResource # Execute a GET request. # Used to get (find) resources. - def get(path) - xml_from_response(request(:get, path, build_request_headers)) + def get(path, headers = {}) + xml_from_response(request(:get, path, build_request_headers(headers))) end # Execute a DELETE request (see HTTP protocol documentation if unfamiliar). # Used to delete resources. - def delete(path) - request(:delete, path, build_request_headers) + def delete(path, headers = {}) + request(:delete, path, build_request_headers(headers)) end # Execute a PUT request (see HTTP protocol documentation if unfamiliar). # Used to update resources. - def put(path, body = '') - request(:put, path, body, build_request_headers) + def put(path, body = '', headers = {}) + request(:put, path, body, build_request_headers(headers)) end # Execute a POST request. # Used to create new resources. - def post(path, body = '') - request(:post, path, body, build_request_headers) + def post(path, body = '', headers = {}) + request(:post, path, body, build_request_headers(headers)) end def xml_from_response(response) @@ -125,8 +125,8 @@ module ActiveResource end # Builds headers for request to remote service. - def build_request_headers - authorization_header.update(self.class.default_header) + def build_request_headers(headers) + authorization_header.update(self.class.default_header).update(headers) end # Sets authorization header; authentication information is pulled from credentials provided with site URI. diff --git a/activeresource/lib/active_resource/custom_methods.rb b/activeresource/lib/active_resource/custom_methods.rb index de99305b93..f4e21714a3 100644 --- a/activeresource/lib/active_resource/custom_methods.rb +++ b/activeresource/lib/active_resource/custom_methods.rb @@ -36,21 +36,21 @@ module ActiveResource alias :orig_delete :delete def get(method_name, options = {}) - connection.get(custom_method_collection_url(method_name, options)) + connection.get(custom_method_collection_url(method_name, options), custom_headers) end def post(method_name, options = {}, body = nil) - connection.post(custom_method_collection_url(method_name, options), body) + connection.post(custom_method_collection_url(method_name, options), body, custom_headers) end def put(method_name, options = {}, body = nil) - connection.put(custom_method_collection_url(method_name, options), body) + connection.put(custom_method_collection_url(method_name, options), body, custom_headers) end # Need to jump through some hoops to retain the original class 'delete' method def delete(custom_method_name, options = {}) if (custom_method_name.is_a?(Symbol)) - connection.delete(custom_method_collection_url(custom_method_name, options)) + connection.delete(custom_method_collection_url(custom_method_name, options), custom_headers) else orig_delete(custom_method_name, options) end @@ -71,23 +71,23 @@ module ActiveResource module InstanceMethods def get(method_name, options = {}) - connection.get(custom_method_element_url(method_name, options)) + connection.get(custom_method_element_url(method_name, options), self.class.custom_headers) end def post(method_name, options = {}, body = nil) if new? - connection.post(custom_method_new_element_url(method_name, options), (body.nil? ? to_xml : body)) + connection.post(custom_method_new_element_url(method_name, options), (body.nil? ? to_xml : body), self.class.custom_headers) else - connection.post(custom_method_element_url(method_name, options), body) + connection.post(custom_method_element_url(method_name, options), body, self.class.custom_headers) end end def put(method_name, options = {}, body = nil) - connection.put(custom_method_element_url(method_name, options), body) + connection.put(custom_method_element_url(method_name, options), body, self.class.custom_headers) end def delete(method_name, options = {}) - connection.delete(custom_method_element_url(method_name, options)) + connection.delete(custom_method_element_url(method_name, options), self.class.custom_headers) end diff --git a/activeresource/test/base_test.rb b/activeresource/test/base_test.rb index 51e1dd3c04..2c823e8e69 100644 --- a/activeresource/test/base_test.rb +++ b/activeresource/test/base_test.rb @@ -13,6 +13,7 @@ class BaseTest < Test::Unit::TestCase ActiveResource::HttpMock.respond_to do |mock| mock.get "/people/1.xml", {}, @matz mock.get "/people/2.xml", {}, @david + mock.get "/people/3.xml", {'key' => 'value'}, nil, 404 mock.put "/people/1.xml", {}, nil, 204 mock.delete "/people/1.xml", {}, nil, 200 mock.delete "/people/2.xml", {}, nil, 400 @@ -198,6 +199,13 @@ class BaseTest < Test::Unit::TestCase assert_equal "Matz", matz.name end + def test_custom_header + Person.custom_headers['key'] = 'value' + assert_raises(ActiveResource::ResourceNotFound) { Person.find(3) } + ensure + Person.custom_headers.delete('key') + end + def test_find_by_id_not_found assert_raises(ActiveResource::ResourceNotFound) { Person.find(99) } assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1) } diff --git a/activeresource/test/connection_test.rb b/activeresource/test/connection_test.rb index b434dd4012..67d5553e72 100644 --- a/activeresource/test/connection_test.rb +++ b/activeresource/test/connection_test.rb @@ -13,16 +13,21 @@ class ConnectionTest < Test::Unit::TestCase @people_empty = [ ].to_xml(:root => 'people-empty-elements') @matz = @matz.to_xml(:root => 'person') @david = @david.to_xml(:root => 'person') + @header = {'key' => 'value'} @default_request_headers = { 'Content-Type' => 'application/xml' } ActiveResource::HttpMock.respond_to do |mock| + mock.get "/people/2.xml", @header, @david mock.get "/people.xml", {}, @people mock.get "/people_single_elements.xml", {}, @people_single mock.get "/people_empty_elements.xml", {}, @people_empty mock.get "/people/1.xml", {}, @matz mock.put "/people/1.xml", {}, nil, 204 + mock.put "/people/2.xml", {}, @header, 204 mock.delete "/people/1.xml", {}, nil, 200 + mock.delete "/people/2.xml", @header, nil, 200 mock.post "/people.xml", {}, nil, 201, 'Location' => '/people/5.xml' + mock.post "/members.xml", {}, @header, 201, 'Location' => '/people/6.xml' end end @@ -79,6 +84,11 @@ class ConnectionTest < Test::Unit::TestCase assert_equal "Matz", matz["name"] end + def test_get_with_header + david = @conn.get("/people/2.xml", @header) + assert_equal "David", david["name"] + end + def test_get_collection people = @conn.get("/people.xml") assert_equal "Matz", people[0]["name"] @@ -100,16 +110,31 @@ class ConnectionTest < Test::Unit::TestCase assert_equal "/people/5.xml", response["Location"] end + def test_post_with_header + response = @conn.post("/members.xml", @header) + assert_equal "/people/6.xml", response["Location"] + end + def test_put response = @conn.put("/people/1.xml") assert_equal 204, response.code end + def test_put_with_header + response = @conn.put("/people/2.xml", @header) + assert_equal 204, response.code + end + def test_delete response = @conn.delete("/people/1.xml") assert_equal 200, response.code end + def test_delete_with_header + response = @conn.delete("/people/2.xml", @header) + assert_equal 200, response.code + end + protected def assert_response_raises(klass, code) assert_raise(klass, "Expected response code #{code} to raise #{klass}") do -- cgit v1.2.3