在整个 rails 个应用程序中使用一个客户端实例进行外部服务
Using one instance of client for external service throughout rails application
这个问题不是关于特定的外部服务,而是关于在整个应用程序中使用相同的对象以防止在每次调用时重新验证。我正在 rails 应用程序上构建一个 ruby,它通过 restforce 连接到 Salesforce REST API。截至目前,我在每个控制器内创建了一个 restforce 对象(客户端)的实例。这显着降低了我的应用程序的速度,因为它在每次页面加载时都会对 salesforce 的 api 进行身份验证。
截至目前,我有一个初始化程序文件,它创建了一个包含凭据(oauth 令牌等)的 restforce 对象。我想在整个应用程序中使用该客户端实例来加快速度。至少,我想在每个控制器中进行一次身份验证,以便每个方法都可以访问该对象的一个经过身份验证的实例。
restforce.rb(初始化文件)
需要 '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
控制器示例
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
上面的控制器说明了我遇到的问题。当我加载 foobar 视图时,它会创建一个新的 restforce 实例。然后当我加载 barfoo 视图时,它会创建一个新的 restforce 实例。无论如何,是否有一个跨控制器的 restforce 实例,或者更好的是,整个应用程序?
我认为这对你来说是更好的方法:
#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
之后你可以简单地使用它:
# 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
将仅创建一次 Restforce
实例。
如果你想在 AR
模型中使用 client
方法,你可以这样做:
# 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)
使用 Singleton 模块的一个很好的替代方法是简单地使用一个常量,您可以在某种初始化程序中设置它。
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']
单例的唯一优势class是初始时间。但这不是 RestForce 的问题(对大多数客户来说应该不是问题)。
这个问题不是关于特定的外部服务,而是关于在整个应用程序中使用相同的对象以防止在每次调用时重新验证。我正在 rails 应用程序上构建一个 ruby,它通过 restforce 连接到 Salesforce REST API。截至目前,我在每个控制器内创建了一个 restforce 对象(客户端)的实例。这显着降低了我的应用程序的速度,因为它在每次页面加载时都会对 salesforce 的 api 进行身份验证。
截至目前,我有一个初始化程序文件,它创建了一个包含凭据(oauth 令牌等)的 restforce 对象。我想在整个应用程序中使用该客户端实例来加快速度。至少,我想在每个控制器中进行一次身份验证,以便每个方法都可以访问该对象的一个经过身份验证的实例。
restforce.rb(初始化文件) 需要 '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
控制器示例
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
上面的控制器说明了我遇到的问题。当我加载 foobar 视图时,它会创建一个新的 restforce 实例。然后当我加载 barfoo 视图时,它会创建一个新的 restforce 实例。无论如何,是否有一个跨控制器的 restforce 实例,或者更好的是,整个应用程序?
我认为这对你来说是更好的方法:
#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
之后你可以简单地使用它:
# 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
将仅创建一次 Restforce
实例。
如果你想在 AR
模型中使用 client
方法,你可以这样做:
# 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)
使用 Singleton 模块的一个很好的替代方法是简单地使用一个常量,您可以在某种初始化程序中设置它。
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']
单例的唯一优势class是初始时间。但这不是 RestForce 的问题(对大多数客户来说应该不是问题)。