从ActiveResource请求中删除.xml扩展名

14

我想使用ActiveResource从第三方API中获取XML数据。我可以使用RESTClient应用程序成功认证和发起请求。我编写了我的应用程序,但在发出请求时遇到了404错误。我添加了:

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

我已经修改了我的development.rb文件并找出了问题所在。API响应非xml结尾的请求时返回xml数据。例如,这个RESTClient请求可以正常工作:

https://api.example.com/contacts

但是ActiveResource正在发送这个请求。

https://api.example.com/contacts.xml
有没有一种“好”方法可以从ActiveResource生成的请求中去掉扩展名? 谢谢。
4个回答

13

您可以使用以下方法从路径中排除格式字符串:

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

1
请注意,此方法仅适用于ActiveResource 4及更高版本。如果您使用的是3.2.x或更早版本,则会引发异常。 - MrTheWalrus

6

您可以重写ActiveResource::Base的方法

将此库添加到/lib/active_resource/extend/目录中,不要忘记取消注释
"config.autoload_paths += %W(#{config.root}/lib)"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

在模型中

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

1
注意,从Rails 3开始,您可能希望将此放在应用程序顶级目录下的/extras中(而不是/lib下),因为如果取消注释config/application.rb中的正确行,则现在是Rails将自动加载的目录。 - benvolioT
这是一个相当武断的解决方案,它会 全局性地 修改ActiveResource的行为。根据需求,更本地化的解决方案可能更好。 - user229044

6

您可能需要在您的模型中覆盖element_path方法。

根据API,当前定义如下:

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

去掉 .#{format.extension} 部分可能会满足你的需求。


是的,这很有用。我找到了一篇更深入介绍ActiveResource和API工作的文章。http://www.quarkruby.com/2008/3/11/consume-non-rails-style-rest-apis - Matt

5

针对类而言,覆盖上述此答案中提到的_path访问器比在整个ActiveResource应用程序范围内打补丁更为简单,后者可能会干扰其他依赖于ActiveResource的资源或宝石。

只需直接将这些方法添加到您的类中:

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

如果您在同一API中访问多个RESTful资源,则应定义自己的基类,以便将常见配置存储在其中。这是一个更好的位置,可以放置自定义的_path方法。
# 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接