2010-07-21 13 views
14

Sto tentando di utilizzare ActiveResource per consumare dati xml da un'API di terze parti. Posso usare l'app RESTClient per autenticare e fare richieste con successo. Ho codificato la mia app e quando faccio una richiesta ottengo un errore 404. Ho aggiunto:Rimuovi estensione .xml dalla richiesta ActiveResource

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

al mio file development.rb e ho capito il problema. L'API risponde con i dati xml alle richieste che NON terminano in xml. EG, questo funziona in RESTClient:

https://api.example.com/contacts 

ma ActiveResource sta inviando questa richiesta invece

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

C'è comunque modo "gentile" per mettere a nudo l'estensione dalla richiesta di essere generato da ActiveResource?

Grazie

risposta

6

probabilmente è necessario eseguire l'override del metodo element_path nel modello.

Secondo l'API, il defintion corrente assomiglia a questo:

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 

Rimozione del # {} format.extension parte potrebbe fare quello che ti serve..

+0

Sì, questo fa il trucco. Ho trovato questo articolo che approfondisce il lavoro con ActiveResource e API. http://www.quarkruby.com/2008/3/11/consume-non-rails-style-rest-apis – Matt

6

È possibile ignorare i metodi di ActiveResource :: Base

Aggiungere questo lib in/directory/lib/active_resource/estendere non dimenticare rimuovere il commento
"config.autoload_paths + =% W (# {config. radice}/lib)" in 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 

nel modello

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

Nota, come di rails 3, potresti voler inserire questo sotto/extra nella directory di livello superiore della tua app (invece di sotto/lib), dato che ora è il rotaie della directory si caricherà automaticamente se si decommenta il file corretto come in config/application.rb. – benvolioT

+0

Questa è una soluzione piuttosto pesante che modifica il comportamento di ActiveResource * application wide *. Una soluzione più localizzata può essere migliore, a seconda delle esigenze. – meagar

4

È molto più semplice sovrascrivere gli accessori _path menzionati in this answer in base a una classe class, piuttosto che in un'applicazione ActiveResource di patch-patch che può interferire con altre risorse o gem che dipendono da ActiveResource.

Basta aggiungere i metodi direttamente alla classe:

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 

Se accedi più risorse RESTful all'interno della stessa API, è necessario definire la propria classe di base in cui configurazione comune può risiedere. Questo è un posto di gran lunga migliore per personalizzati _path metodi:

# 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

è possibile escludere la stringa di formato da percorsi con:

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

Si noti che funziona solo da ActiveResource 4. Se si è bloccati su 3.2.xo precedenti, si genera un'eccezione. – MrTheWalrus