Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #6979: active_resource_custom_methods_patch_unblocked_fixed_tests.diff

File active_resource_custom_methods_patch_unblocked_fixed_tests.diff, 10.5 kB (added by rwdaigle, 2 years ago)

Request syntax custom methods functionality with tests fixed.

  • test/base/custom_methods_test.rb

    old new  
     1require "#{File.dirname(__FILE__)}/../abstract_unit" 
     2require "#{File.dirname(__FILE__)}/../fixtures/person" 
     3require "#{File.dirname(__FILE__)}/../fixtures/street_address" 
     4 
     5class CustomMethodsTest < Test::Unit::TestCase 
     6  def setup 
     7    @matz  = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person') 
     8    @matz_deep  = { :id => 1, :name => 'Matz', :other => 'other' }.to_xml(:root => 'person') 
     9    @ryan  = { :name => 'Ryan' }.to_xml(:root => 'person') 
     10    @addy  = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address') 
     11    @addy_deep  = { :id => 1, :street => '12345 Street', :zip => "27519" }.to_xml(:root => 'address') 
     12    @default_request_headers = { 'Content-Type' => 'application/xml' } 
     13     
     14    ActiveResource::HttpMock.respond_to do |mock| 
     15      mock.get    "/people/1.xml",             {}, @matz 
     16      mock.get    "/people/1.xml;shallow", {}, @matz 
     17      mock.get    "/people/1.xml;deep", {}, @matz_deep 
     18      mock.get    "/people.xml;retrieve?name=Matz", {}, "<people>#{@matz}</people>" 
     19      mock.put    "/people/1.xml;promote?position=Manager", {}, nil, 204 
     20      mock.put    "/people.xml;promote?name=Matz", {}, nil, 204, {} 
     21      mock.put    "/people.xml;sort?by=name", {}, nil, 204 
     22      mock.delete "/people.xml;deactivate?name=Matz", {}, nil, 200 
     23      mock.delete "/people/1.xml;deactivate", {}, nil, 200 
     24      mock.post   "/people.xml/new;register",      {}, @ryan, 201, 'Location' => '/people/5.xml' 
     25      mock.get    "/people/1/addresses/1.xml", {}, @addy 
     26      mock.get    "/people/1/addresses/1.xml;deep", {}, @addy_deep 
     27      mock.put    "/people/1/addresses/1.xml;normalize_phone?locale=US", {}, nil, 204 
     28      mock.put    "/people/1/addresses.xml;sort?by=name", {}, nil, 204 
     29      mock.post   "/people/1/addresses.xml/new;link", {}, { :street => '12345 Street' }.to_xml(:root => 'address'), 201, 'Location' => '/people/1/addresses/2.xml' 
     30    end 
     31  end   
     32   
     33  def test_custom_collection_method 
     34     
     35    # GET 
     36    assert_equal([{ "id" => 1, "name" => 'Matz' }], Person.get(:retrieve, :name => 'Matz')) 
     37     
     38    # PUT 
     39    assert_equal ActiveResource::Response.new({}, 204, {}), 
     40                   Person.put(:promote, {:name => 'Matz'}, 'atestbody') 
     41    assert_equal ActiveResource::Response.new({}, 204, {}), Person.put(:sort, :by => 'name') 
     42     
     43    # DELETE 
     44    Person.delete :deactivate, :name => 'Matz' 
     45     
     46    # Nested resource 
     47    assert_equal ActiveResource::Response.new({}, 204, {}), StreetAddress.put(:sort, :person_id => 1, :by => 'name') 
     48  end 
     49   
     50  def test_custom_element_method 
     51     
     52    # Test GET against an element URL 
     53    assert_equal Person.find(1).get(:shallow), {"id" => 1, "name" => 'Matz'} 
     54    assert_equal Person.find(1).get(:deep), {"id" => 1, "name" => 'Matz', "other" => 'other'} 
     55     
     56    # Test PUT against an element URL 
     57    assert_equal ActiveResource::Response.new({}, 204, {}), Person.find(1).put(:promote, {:position => 'Manager'}, 'body') 
     58     
     59    # Test DELETE against an element URL 
     60    assert_equal ActiveResource::Response.new({}, 200, {}), Person.find(1).delete(:deactivate) 
     61     
     62    # With nested resources 
     63    assert_equal StreetAddress.find(1, :person_id => 1).get(:deep), 
     64                  { "id" => 1, "street" => '12345 Street', "zip" => "27519" } 
     65    assert_equal ActiveResource::Response.new({}, 204, {}), 
     66                   StreetAddress.find(1, :person_id => 1).put(:normalize_phone, :locale => 'US') 
     67  end 
     68   
     69  def test_custom_new_element_method 
     70     
     71    # Test POST against a new element URL 
     72    ryan = Person.new(:name => 'Ryan') 
     73    assert_equal ActiveResource::Response.new(@ryan, 201, {'Location' => '/people/5.xml'}), ryan.post(:register) 
     74     
     75    # Test POST against a nested collection URL 
     76    addy = StreetAddress.new({:street => '123 Test Dr.'}, {:person_id => 1}) 
     77    assert_equal ActiveResource::Response.new({ :street => '12345 Street' }.to_xml(:root => 'address'),  
     78                   201, {'Location' => '/people/1/addresses/2.xml'}), 
     79                 addy.post(:link) 
     80  end 
     81   
     82  def teardown 
     83    ActiveResource::HttpMock.reset! 
     84  end 
     85end 
  • test/base_test.rb

    old new  
    9595    assert_equal '/people.xml?gender=', Person.collection_path(:gender => nil) 
    9696 
    9797    assert_equal '/people.xml?gender=male', Person.collection_path('gender' => 'male') 
    98     assert_equal '/people.xml?gender=male&student=true', Person.collection_path(:gender => 'male', :student => true) 
     98     
     99    # Use includes? because ordering of param hash is not guaranteed 
     100    assert Person.collection_path(:gender => 'male', :student => true).include?('/people.xml?') 
     101    assert Person.collection_path(:gender => 'male', :student => true).include?('gender=male') 
     102    assert Person.collection_path(:gender => 'male', :student => true).include?('student=true') 
    99103 
    100104    assert_equal '/people.xml?name[]=bob&name[]=your+uncle%2Bme&name[]=&name[]=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false]) 
    101105  end 
  • lib/active_resource/custom_methods.rb

    old new  
     1# Support custom REST methods, in synch with the Simply RESTful 
     2# plugin. 
     3# 
     4# I.e. on the server routes config you would have: 
     5# 
     6#   map.resources :people, :new => { :register => :post }, 
     7#                          :element => { :promote => :put, :deactivate => :delete } 
     8#                          :collection => { :active => :get } 
     9# 
     10#  Which creates routes for the following http requests 
     11# 
     12#  POST: /people/new;register #=> PeopleController.register 
     13#  PUT: /people/1;promote #=> PeopleController.promote(:id => 1) 
     14#  DELETE: /people/1;deactivate #=> PeopleController.deactivate(:id => 1) 
     15#  GET: /people;active #=> PeopleController.active 
     16# 
     17# This module provides the ability for ActiveResource to call these 
     18# custom REST methods and get the response back. 
     19# 
     20#   class Person < ActiveResource::Base 
     21#     self.site = "http://37s.sunrise.i:3000" 
     22#   end 
     23# 
     24#   Person.new(:name => 'Ryan).post(:register) #=> {:id => 1, :name => 'Ryan'} 
     25# 
     26#   Person.find(1).put(:promote, :position => 'Manager') #=> <Response::XXXX> 
     27#   Person.find(1).delete(:deactivate) #=> <Response::XXXX> 
     28# 
     29#   Person.get(:active) #=> [{:id => 1, :name => 'Ryan'}, {:id => 2, :name => 'Joe'}] 
     30#    
     31module ActiveResource 
     32  module CustomMethods 
     33       
     34    def self.included(within) 
     35      within.class_eval do 
     36        class << self 
     37           
     38          include ActiveResource::CustomMethods::ClassMethods 
     39           
     40          alias :orig_delete :delete 
     41           
     42          # Define the class level Http request methods - which are tied 
     43          # to a call on the collection url. 
     44       
     45          def get(method_name, options = {}) 
     46            connection.get(custom_method_collection_url(method_name, options)) 
     47          end 
     48       
     49          def post(method_name, options = {}, body = nil) 
     50            connection.post(custom_method_collection_url(method_name, options), body) 
     51          end 
     52       
     53          def put(method_name, options = {}, body = nil) 
     54            connection.put(custom_method_collection_url(method_name, options), body) 
     55          end 
     56       
     57          # Need to jump through some hoops to retain the original class 'delete' method 
     58          def delete(custom_method_name, options = {}) 
     59            if(custom_method_name.is_a?(Symbol)) 
     60              connection.delete(custom_method_collection_url(custom_method_name, options)) 
     61            else 
     62              orig_delete(custom_method_name) 
     63            end 
     64          end 
     65        end 
     66 
     67      end 
     68 
     69      within.send(:include, ActiveResource::CustomMethods::InstanceMethods) 
     70    end 
     71     
     72    module ClassMethods 
     73      def custom_method_collection_url(method_name, options = {}) 
     74        "#{prefix(options)}#{collection_name}.xml;#{method_name}#{query_string(options)}" 
     75      end 
     76    end 
     77     
     78    module InstanceMethods 
     79       
     80      def get(method_name, options = {}) 
     81        connection.get(custom_method_element_url(method_name, options)) 
     82      end 
     83       
     84      def post(method_name, options = {}, body = nil) 
     85        if(new?) 
     86          connection.post(custom_method_new_element_url(method_name, options), 
     87            (body.nil? ? to_xml : body)) 
     88        else 
     89          connection.post(custom_method_element_url(method_name, options), body) 
     90        end 
     91      end 
     92       
     93      def put(method_name, options = {}, body = nil) 
     94        connection.put(custom_method_element_url(method_name, options), body) 
     95      end 
     96       
     97      def delete(method_name, options = {}) 
     98        connection.delete(custom_method_element_url(method_name, options)) 
     99      end 
     100       
     101      private 
     102       
     103        def custom_method_element_url(method_name, options = {}) 
     104          "#{self.class.prefix(prefix_options)}#{self.class.collection_name}/#{id}.xml;#{method_name}#{self.class.send(:query_string, options)}" 
     105        end 
     106       
     107        def custom_method_new_element_url(method_name, options = {}) 
     108          "#{self.class.prefix(prefix_options)}#{self.class.collection_name}.xml/new;#{method_name}#{self.class.send(:query_string, options)}" 
     109        end 
     110    end 
     111  end 
     112   
     113end 
  • lib/active_resource/http_mock.rb

    old new  
    110110    def []=(key, value) 
    111111      headers[key] = value 
    112112    end 
     113     
     114    def ==(other) 
     115      if(other.is_a?(Response)) 
     116        other.body == body && other.message == message && other.headers == headers 
     117      else 
     118        false 
     119      end 
     120    end 
    113121  end 
    114122 
    115123  class Connection 
  • lib/active_resource.rb

    old new  
    3737require 'active_resource/base' 
    3838require 'active_resource/struct' 
    3939require 'active_resource/validations' 
     40require 'active_resource/custom_methods' 
    4041 
    4142module ActiveResource 
    4243  Base.class_eval do 
    4344    include Validations 
     45    include CustomMethods 
    4446  end 
    4547end