我有2个RESTful Rails应用程序,我正试图互相交谈。两者都是用Rails 3编写的(目前是beta3)。对服务的请求将需要使用api密钥,这只是每个请求都需要的参数。我似乎无法找到有关如何执行此操作的任何信息。
您可以通过site =方法定义资源连接到的网址。应该有一个等效的query_params =方法或类似方法。
我发现有一篇很好的博客文章与此有关,而且是从2008年10月开始,因此对Rails 3来说并不完全有用。
更新:我有个想法。小型机架中间件或金属是否可以解决这个问题?它可以通过请求,将其添加到api_key上。
答案 0 :(得分:21)
使用model#prefix_options这是一个散列,用于将params传递给查询字符串(甚至作为Model.prefix部分的子目录,例如“/ myresource /:param /”将被prefix_options [:param]的值替换在前缀中找不到的任何哈希键都会被添加到查询字符串中,这就是我们想要的情况。)
class Model < ActiveResource::Base
class << self
attr_accessor :api_key
end
def save
prefix_options[:api_key] = self.class.api_key
super
end
end
Model.site = 'http://yoursite/'
Model.api_key = 'xyz123'
m = Model.new(:field_1 => 'value 1')
# hits http://yoursite:80/models.xml?api_key=xyz123
m.save
答案 1 :(得分:10)
我最近遇到过类似的问题,如果您使用的是Rails3,它支持使用自定义标题,这可以让这些情况更轻松。
在您提出请求的一边,添加
headers['app_key'] = 'Your_App_Key'
到您从ActiveResource :: Base
继承的类在您是服务器上,对于身份验证,只需将其作为
接收 request.headers['HTTP_APP_KEY']
例如:
class Magic < ActiveResource::Base
headers['app_key'] = 'Your_App_Key'
end
现在Magic.get,Magic.find,Magic.post都将发送app_key
答案 2 :(得分:4)
我有更好的解决方案!我在中间件中尝试使用Rack,但我没有找到任何解决方案....
我建议您使用此模块来覆盖ActiveReouse :: Base
的方法在/ lib / active_resource / extend /目录中添加此lib不要忘记取消注释 config / application.rb
中的“config.autoload_paths + =%W(#{config.root} / lib)”module ActiveResource #:nodoc:
module Extend
module AuthWithApi
module ClassMethods
def element_path_with_auth(*args)
element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
end
def new_element_path_with_auth(*args)
new_element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
end
def collection_path_with_auth(*args)
collection_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
end
end
def self.included(base)
base.class_eval do
extend ClassMethods
class << self
alias_method_chain :element_path, :auth
alias_method_chain :new_element_path, :auth
alias_method_chain :collection_path, :auth
attr_accessor :api_key
end
end
end
end
end
end
在模型中
class Post < ActiveResource::Base
include ActiveResource::Extend::AuthWithApi
self.site = "http://application.localhost.com:3000/"
self.format = :json
self.api_key = 'jCxKPj8wJJdOnQJB8ERy'
schema do
string :title
string :content
end
end
答案 3 :(得分:3)
基于Joel Azemar的回答,但我不得不做出一些改变...... 首先,在我使用的活动资源gem(2.3.8)中,没有&#39; new_element_path&#39;,所以显然失败的别名.. 其次,我更新了令牌添加到查询的方式,因为它会在您自己添加更多参数时立即中断。例如。请求http://example.com/api/v1/clients.xml?vat=0123456789?token=xEIx6fBsxy6sKLJMPVM4(通知?token = i.o.&amp; token =)
这是我更新的代码段auth_with_api.rb;
module ActiveResource #:nodoc:
module Extend
module AuthWithApi
module ClassMethods
def element_path_with_auth(id, prefix_options = {}, query_options = nil)
query_options.merge!({:token => self.api_key})
element_path_without_auth(id, prefix_options, query_options)
end
def collection_path_with_auth(prefix_options = {}, query_options = nil)
query_options.merge!({:token => self.api_key})
collection_path_without_auth(prefix_options, query_options)
end
end
def self.included(base)
base.class_eval do
extend ClassMethods
class << self
alias_method_chain :element_path, :auth
# alias_method_chain :new_element_path, :auth
alias_method_chain :collection_path, :auth
attr_accessor :api_key
end
end
end
end
end
end
答案 4 :(得分:2)
Active Resource目前没有将api密钥传递给远程服务的好方法。将api_key作为参数传递将其添加到远程服务上的对象属性中,我假设这不是您的行为。这当然不是我需要的行为
答案 5 :(得分:2)
我建议你有一个继承自ActiveResource::Base
的基类,并覆盖self.collection_path
和self.element_path
类方法,以便始终注入API KEY,如:
class Base < ActiveResource::Base
def self.collection_path(prefix_options = {}, query_options = {})
super(prefix_options, query_options.merge(api_key: THE_API_KEY))
end
def self.element_path(id, prefix_options = {}, query_options = {})
super(id, prefix_options, query_options.merge(api_key: THE_API_KEY))
end
end
class User < Base; end
User.all # GET /users/?api_key=THE_API_KEY
这将始终在您的ActiveResource方法调用中注入您的API_KEY。
答案 6 :(得分:1)
活动资源对象的行为很像(简化的)Active Record对象。 如果您希望传递新参数,则可以通过将其添加为属性在AR对象上进行设置。例如:
jane = Person.create(:first => 'Jane', :last => 'Doe', :api_key => THE_API_KEY)
它应该将api_key作为参数传递给所有其他参数。