在整个rails应用程序中使用一个客户端实例进行外部服务

时间:2015-04-23 23:32:12

标签: ruby-on-rails ruby ruby-on-rails-4 salesforce

这个问题不是关于特定的外部服务,而是关于在整个应用程序中使用相同的对象以防止在每次调用时重新进行身份验证。我正在构建一个ruby on rails应用程序,它通过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实例,甚至更好吗?

2 个答案:

答案 0 :(得分:5)

我认为这是更好的方式:

#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个实例一次。

如果您想在client模型中使用AR方法,则可以执行以下操作:

# 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)

答案 1 :(得分:0)

使用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']

单身人士课程的唯一优势是初始时间。但这不是RestForce的问题(并且不应该是大多数客户的问题)。