Reputation: 1123
This question isn't about a specific external service, but about using the same object throughout an application to prevent re-authentication at every call. I'm building a ruby on rails application that connects to the Salesforce REST API via restforce. As of right now, I create an instance of the restforce object (client) inside of every controller. This slows my application down significantly because it is authenticating into salesforce's api on every page load.
As of right now, I have an initializer file that creates a restforce object that includes the credentials (oauth token, etc.). I would like to use that instance of the client throughout the application to speed things up. At the very least, I would like to authenticate once in each controller so each method has access to one authenticated instance of the object.
restforce.rb (initializer file) require 'restforce'
class RestforceClient
def restforce
client = Restforce.new :username => ENV['SALESFORCE_USERNAME'],
:password => ENV['SALESFORCE_PASSWORD'],
:security_token => ENV['SALESFORCE_SECURITY_TOKEN'],
:client_id => ENV['SALESFORCE_CLIENT_ID'],
:client_secret => ENV['SALESFORCE_CLIENT_SECRET'],
:host => ENV['SALESFORCE_HOST'],
:debugging => ENV['TRUE']
end
end
controller example
def foobar
@user = current_user
client = Restforce.new
@fetchdata = client.query("select X from y")
end
def barfoo
@user = current_user
client = Restforce.new
@fetchdata = client.query("select X from Z")
end
The above controller illustrates the problem I'm encountering. When I load the foobar view, It creates a new instance of restforce. Then when I load the barfoo view, it creates a new instance of restforce. Is there anyway to have one instance of restforce across the controller, or even better, the whole application?
Upvotes: 2
Views: 2017
Reputation: 5233
I think this is the better way for you:
#config/initializers/client.rb
class RestforceClient
include Singleton
def restforce
@client ||= \
Restforce.new :username => ENV['SALESFORCE_USERNAME'],
:password => ENV['SALESFORCE_PASSWORD'],
:security_token => ENV['SALESFORCE_SECURITY_TOKEN'],
:client_id => ENV['SALESFORCE_CLIENT_ID'],
:client_secret => ENV['SALESFORCE_CLIENT_SECRET'],
:host => ENV['SALESFORCE_HOST'],
:debugging => ENV['TRUE']
end
end
# app/controllers/application_controller.rb
private
def client
RestforceClient.instance.restforce
end
helper_method :client
After that you can simply use it:
# controller
def foobar
@user = current_user
@fetchdata = client.query("select X from y")
end
# view
<%= client.query("select X from y") %>
# other services
class MyService
def some_methods
result = RestforceClient.instance.restforce
#...
end
end
RestforceClient
will create Restforce
instance only once.
If you want client
method in the AR
models you can do this:
# config/initializers/extend_ar.rb
module ActiveRecordExtension
extend ActiveSupport::Concern
def client
RestforceClient.instance.restforce
end
end
# include the extension
ActiveRecord::Base.send(:include, ActiveRecordExtension)
Upvotes: 6
Reputation: 3285
A good alternative to use Singleton module is to simply use a Constant that you can setup in an Initializer of some sort.
RestforceClient = Restforce.new :username => ENV['SALESFORCE_USERNAME'],
:password => ENV['SALESFORCE_PASSWORD'],
:security_token => ENV['SALESFORCE_SECURITY_TOKEN'],
:client_id => ENV['SALESFORCE_CLIENT_ID'],
:client_secret => ENV['SALESFORCE_CLIENT_SECRET'],
:host => ENV['SALESFORCE_HOST'],
:debugging => ENV['TRUE']
The only advantage of a singleton class is the initial time. But this is not an issue with RestForce (and should not be an issue with most clients).
Upvotes: 0