Is it thread safe to set Active Resource HTTP authentication on a per-user basis?
Monkey patch the host
, user
and password
methods of ActiveResource::Base
class:
class ActiveResource::Base
# store the attribute value in a thread local variable
class << self
%w(host user password).each do |attr|
define_method(attr) do
Thread.current["active_resource.#{attr}"]
end
define_method("#{attr}=") do |val|
Thread.current["active_resource.#{attr}"] = val
end
end
end
end
Now set the credentials in every request
class ApplicationController < ActionController::Base
around_filter :set_api_credentials
private
# set the credentials in every request
def set_api_credentials
ActiveResource::Base.host,
ActiveResource::Base.user,
ActiveResource::Base.password = current_user_credentials
yield
ensure
ActiveResource::Base.host =
ActiveResource::Base.user =
ActiveResource::Base.password = nil
end
DEFAULT_HOST, DEFAULT_USER, DEFAULT_PASSWORD= [
"http://www.foo.com", "user1", "user78102" ]
def current_user_credentials
current_user.present? ?
[ current_user.host, current_user.login, current_user.password] :
[ DEFAULT_HOST, DEFAULT_USER, DEFAULT_PASSWORD]
end
end
Rails ActiveResource with custom REST collection schema?
ActiveResource by default has very strong expectations concerning format of data returned by the API, but you can provide your own format for scenarios like this.
Any Ruby object implementing a few expected methods can be used as a format. ActiveResource itself implements formats as modules, so we will stick to this convention.
Being a lazy man, I will reuse the standard JsonFormat implementation and only override method decode
:
module CustomJsonFormat
include ActiveResource::Formats::JsonFormat
extend self
def decode(json)
ActiveSupport::JSON.decode(json)['data']
end
end
Now we just tell the ActiveResource subclass to use it:
class BaseModel < ActiveResource::Base
self.format = CustomJsonFormat
# ... set self.site, self.headers etc.
end
Rails ActiveResource Associations
ActiveResource does not support associations. But it doen't prevent you from setting/getting complex data to/from a ActiveResource object. Here is how I would implement it:
Server side model
class Customer < ActiveRecord::Base
has_and_belongs_to_many :groups
accepts_nested_attributes_for :groups
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :customers
accepts_nested_attributes_for :customers
end
Server side GroupsController
def show
@group = Group.find(params[:id])
respond_to do |format|
format.xml { render :xml => @group.to_xml(:include => :customers) }
end
end
Client side model
class Customer < ActiveResource::Base
end
class Group < ActiveResource::Base
end
Client side GroupsController
def edit
@group = Group.find(params[:id])
end
def update
@group = Group.find(params[:id])
if @group.load(params[:group]).save
else
end
end
Client View: Accessing customer from Group object
# access customers using attributes method.
@group.customers.each do |customer|
# access customer fields.
end
Client side: Setting customer to Group object
group.attributes['customers'] ||= [] # Initialize customer array.
group.customers << Customer.build
Related Topics
Assign to an Array and Replace Emerged Nil Values
How to Recursively Flatten a Yaml File into a JSON Object Where Keys Are Dot Separated Strings
Gem Install JSON Fails with Redifinition of Struct Timezone/Timespec
Why Should You Avoid the Then Keyword in Ruby
Empty Strings at the Beginning and End of Split
How Does Sinatra Define and Invoke the Get Method
Permanently Switching User in Capistrano 3 (Separate Authorization & Deploy)
Ruby Getting Deeply Nested JSON API Data
Wicked_Pdf Is Not Rendering Header
How to HTML_Escape Text Data in a Sinatra App
Ruby Range: Operators in Case Statement
Validating Date Format Using Regular Expression
Why Are Parenthesis Sometimes Required in Ruby
Interpolating Regexes into Another Regex
Ruby 1.9 Ramaze App Failing with "Illegal Instruction"