Добавить ключ api для каждого запроса в ActiveResource
У меня есть 2 RESTful Rails приложения, которые я пытаюсь поговорить друг с другом. Оба они написаны в Rails 3 (beta3 на данный момент). Запросы к службе потребуют использования ключа api, который является всего лишь параметром, который должен выполняться по каждому запросу. Я не могу найти какую-либо информацию о том, как это сделать.
Вы определяете URL-адрес, к которому подключается ресурс, с помощью метода site =. Должен быть эквивалентный метод query_params = или аналогичный.
Есть одно хорошее сообщение в блоге, которое я нашел, связанное с этим, и с октября 2008 года, поэтому не очень полезно для Rails 3.
Обновление. У меня была мысль. Будет ли на это ответным промежуточным программным обеспечением Rack или Metal? Он может просто пройти через запрос, нажав на него api_key.
Ответы
Ответ 1
Использовать модель # prefix_options, которая является хешем для передачи параметров в строку запроса (или даже в качестве подстановок для частей 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
Ответ 2
Недавно я столкнулся с подобной проблемой, если вы на 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
Ответ 3
У меня гораздо приятнее решение! Я пытаюсь использовать Rack в промежуточном программном обеспечении, но я не нахожу решения таким образом....
Я предлагаю вам этот модуль для переопределения методов ActiveReouse:: Base
Добавьте этот lib в каталог /lib/active _resource/extend/, не забудьте раскомментировать
"config.autoload_paths + =% W (# {config.root}/lib)" в config/application.rb
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
Ответ 4
На основании ответа Джоэла Аземара, но мне пришлось внести некоторые изменения.
Прежде всего, в массиве активных ресурсов, который я использовал (2.3.8), нет "new_element_path", поэтому сглаживание явно не получилось.
Во-вторых, я обновил способ добавления токена в запрос, потому что, как и было, он сломается, как только вы добавите больше параметров самостоятельно. Например. запрос http://example.com/api/v1/clients.xml?vat=0123456789?token=xEIx6fBsxy6sKLJMPVM4 (уведомление? токен = i.o. & токен =)
Здесь мой обновленный фрагмент 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
Ответ 5
Активный ресурс в настоящее время не имеет хорошего способа передать ключ api удаленной службе. Передача api_key в качестве параметра добавит его к атрибутам объектов в удаленной службе, я предполагаю, что это не то поведение, которое вы хотели бы. Это, конечно, не то поведение, в котором я нуждался.
Ответ 6
Объект активного ресурса ведет себя как объект (упрощенная) Active Record.
Если вы хотите передать новый параметр, вы можете установить его на AR-объект, добавив его как атрибут. например:
jane = Person.create(:first => 'Jane', :last => 'Doe', :api_key => THE_API_KEY)
он должен передать api_key в качестве параметра вместе со всеми остальными.
Ответ 7
Я бы рекомендовал, чтобы у вас был базовый класс, наследующий от 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
Это всегда будет вводить ваш API_KEY в вызовы метода ActiveResource.