2010-07-21 12 views
14

Estoy tratando de usar ActiveResource para consumir datos xml de una API de terceros. Puedo utilizar la aplicación RESTClient para autenticar y realizar solicitudes con éxito. Codifiqué mi aplicación y cuando hago una solicitud obtengo un error 404. Añadí:Eliminar la extensión .xml de la solicitud de ActiveResource

ActiveResource::Base.logger = Logger.new(STDERR) 

a mi archivo development.rb y descubierto el problema. La API responde con datos xml a las solicitudes que NO terminan en xml. Por ejemplo, esto funciona en RESTClient:

https://api.example.com/contacts 

pero ActiveResource está enviando esta solicitud lugar

https://api.example.com/contacts.xml 

¿Hay alguna manera "agradable" para despojar a la extensión de la petición generada por ActiveResource?

Gracias

Respuesta

6

es probable que tenga que sustituir el método element_path en su modelo.

De acuerdo con la API, el Defintion actual se parece a esto:

def element_path(id, prefix_options = {}, query_options = nil) 
    prefix_options, query_options = split_options(prefix_options) if query_options.nil? 
    "#{prefix(prefix_options)}#{collection_name}/#{id}.#{format.extension}#{query_string(query_options)}" 
end 

Extracción del # {} format.extension parte podría hacer lo que tiene..

+0

Sí, esto hace el truco. Encontré este artículo que profundiza en el trabajo con ActiveResource y API. http://www.quarkruby.com/2008/3/11/consume-non-rails-style-rest-apis – Matt

6

Puede reemplazar los métodos de ActiveResource :: Base

Añadir este lib/lib/active_resource// directorio de extender no se olvide descomentar
"config.autoload_paths + =% W (# {config. raíz}/lib)" en config/application.rb

module ActiveResource #:nodoc: 
    module Extend 
    module WithoutExtension 
     module ClassMethods 
     def element_path_with_extension(*args) 
      element_path_without_extension(*args).gsub(/.json|.xml/,'') 
     end 
     def new_element_path_with_extension(*args) 
      new_element_path_without_extension(*args).gsub(/.json|.xml/,'') 
     end 
     def collection_path_with_extension(*args) 
      collection_path_without_extension(*args).gsub(/.json|.xml/,'') 
     end 
     end 

     def self.included(base) 
     base.class_eval do 
      extend ClassMethods 
      class << self 
      alias_method_chain :element_path, :extension 
      alias_method_chain :new_element_path, :extension 
      alias_method_chain :collection_path, :extension 
      end 
     end 
     end 
    end 
    end 
end 

en el modelo

class MyModel < ActiveResource::Base 
    include ActiveResource::Extend::WithoutExtension 
end 
+1

Nota, a partir de los rails 3, es posible que desee poner esto debajo/extras en el directorio de nivel superior de su aplicación (en lugar de under/lib), ya que ahora el directorio rails se cargará automáticamente si eliminas el comentario correcto en config/application.rb. – benvolioT

+0

Esta es una solución bastante estricta que modifica el comportamiento de ActiveResource * application wide *. Una solución más localizada puede ser mejor, dependiendo de los requisitos. – meagar

4

Es mucho más simple anular los accesos _path mencionados en this answer clase por clase, en lugar de aplicar parches a toda la aplicación ActiveResource que pueden interferir con otros recursos o gemas que dependen de ActiveResource.

Sólo tiene que añadir los métodos directamente a su clase:

class Contact < ActiveResource::Base 

    def element_path 
    super.gsub(/\.xml/, "") 
    end 

    def new_element_path 
    super.gsub(/\.xml/, "") 
    end 

    def collection_path 
    super.gsub(/\.xml/, "") 
    end 
end 

Si accede a múltiples recursos REST API dentro de la misma, debe definir su propia clase base, donde puede residir configuración común. Este es un lugar mucho mejor para personalizados _path métodos:

# app/models/api/base.rb 
class Api::Base < ActiveResource::Base 
    self.site  = "http://crazy-apis.com" 
    self.username = "..." 
    self.password = "..." 
    self.prefix = "/my-api/" 

    # Strip .xml extension off generated URLs 
    def element_path 
    super.gsub(/\.xml/, "") 
    end 
    # def new_element_path... 
    # def collection_path... 
end 

# app/models/api/contact.rb 
class Api::Contact < Api::Base 

end 

# app/models/api/payment.rb 
class Api::Payment < Api::Base 

end 

# Usage: 

Api::Contact.all()  # GET http://crazy-apis.com/my-api/contacts 
Api::Payment.new().save # POST http://crazy-apis.com/my-api/payments 
11

puede excluir la cadena de formato de caminos con:

class MyModel < ActiveResource::Base 
    self.include_format_in_path = false 
end 
+1

Tenga en cuenta que esto solo funciona a partir de ActiveResource 4. Si está atascado en 3.2.xo anterior, se generará una excepción. – MrTheWalrus

Cuestiones relacionadas