简体   繁体   English

干燥Rails控制器

[英]Drying up Rails controllers

I have an application in Ruby/Rails where I am going to have to connect to a third-party application (Xero accounting) in order to send/pull data. 我在Ruby / Rails中有一个应用程序,在该应用程序中,我必须连接到第三方应用程序(Xero记帐)才能发送/提取数据。 This happens in several controllers thoughout the application. 在整个应用程序中,这会在多个控制器中发生。 However, whilst the specifics are different, the actual connection is the same, and looks like this: 但是,尽管细节不同,但实际连接是相同的,看起来像这样:

require 'xero_gateway'
xero_config = YAML.load_file("#{Rails.root}/config/xero.yml")["testing"]
xero_private_key = "#{ENV['HOME']}/certs/breathehr_xero.key" || ENV["xero_private_key"]
xero_gateway = XeroGateway::PrivateApp.new(xero_config['consumer_key'], xero_config['consumer_secret'], xero_private_key)

The next step of the code might be fetch something, like an invoice, as in: 代码的下一步可能是获取某些内容,例如发票,如下所示:

xero_gateway.get_invoice('INV-001')

Or, in another controller, it might be to create a contact, such as: 或者,在另一个控制器中,可能是要创建一个联系人,例如:

xero_gateway.build_contact

Is there somewhere I can put the connection code so that I can end up just calling xero_gateway in each specific controller? 有什么地方可以放置连接代码,以便最终xero_gateway在每个特定控制器中调用xero_gateway It doesn't feel right to be repeating the same code again and again each time I have to authenticate and connect. 每次必须进行身份验证和连接时,一次又一次重复相同的代码是不对的。

To build on @Dave Newton's answer: 以@Dave Newton的答案为基础:

You would create a "provider" class that marries an object factory to some configuration: 您将创建一个“ provider”类,该类将对象工厂与某种配置结合起来:

File: lib/xero_gateway_provider.rb 档案: lib/xero_gateway_provider.rb

require 'xero_gateway'

class XeroGatewayProvider
    cattr_accessor :default_private_key, :default_consumer_key, :default_consumer_secret

    def initialize(overrides = {})
        @private_key = overrides[:private_key] || self.class.default_private_key
        @consumer_key = overrides[:consumer_key] || self.class.default_consumer_key
        @consumer_secret = overrides[:consumer_secret] || self.class.default_consumer_secret
    end

    def create_private_app
        XeroGateway::PrivateApp.new(@consumer_key, @consumer_secret, @private_key)
    end
end

Then you could create a Rails initializer: config/initializers/xero_gateway_provider.rb 然后,您可以创建一个Rails初始化程序: config/initializers/xero_gateway_provider.rb

require 'xero_gateway_provider'
conf = YAML.load_file("#{Rails.root}/config/xero.yml")[Rails.env]
XeroGatewayProvider.default_private_key = "#{ENV['HOME']}/certs/breathehr_xero.key" || ENV["xero_private_key"]
XeroGatewayProvider.default_consumer_key = conf["consumer_key"]
XeroGatewayProvider.default_consumer_secret = conf["consumer_secret"]

And to use it: 并使用它:

# Using default configs
provider = XeroGatewayProvider.new;
private_app = provider.create_private_app
private_app.get_invoice("...")

# Using overrides
provider = XeroGatewayProvider.new :consumer_key => '...', :consumer_secret => '...';
private_app = provider.create_private_app
private_app.get_invoice("...")

Edit: Just realized there is no point to instantiating XeroGatewayProvider if it uses class level properties, so I made them defaults allowing you to configure each provider individually. 编辑:刚刚意识到,如果XeroGatewayProvider使用类级别的属性,则没有必要实例化,因此我将它们设置为默认值,允许您分别配置每个提供程序。

Also @Gareth Burrows comment on where to put and name the class, I think this would fit just fine in the lib/ directory. @Gareth Burrows也对放置和命名该类的位置发表评论,我认为这在lib /目录中就可以了。 See the edits to the post for specifics. 有关详细信息,请参见帖子的编辑。

You can create a regular ruby class in the models folder called Xero or something and do this code in the initializer. 您可以在models文件夹中创建一个名为Xero或其他名称的常规ruby类,并在初始化程序中执行此代码。

require 'xero_gateway'
class Xero
  def initialize
    xero_config = YAML.load_file("#{Rails.root}/config/xero.yml")["testing"]
    xero_private_key = "#{ENV['HOME']}/certs/breathehr_xero.key" || ENV["xero_private_key"]
    xero_gateway = XeroGateway::PrivateApp.new(xero_config['consumer_key'],     xero_config['consumer_secret'], xero_private_key)
  end
end

And then just call: 然后只需调用:

xero_gateway = Xero.new

Another option is to create an initializer in the initializers/ folder. 另一种选择是在initializers /文件夹中创建一个初始化器。 xero_gateway.rb xero_gateway.rb

And put the initialization code in there. 并将初始化代码放在其中。 This way it will be parsed only on application startup. 这样,它将仅在应用程序启动时进行解析。

You could put it just about anywhere, including: 您可以将其放置在几乎任何地方,包括:

  1. A utility class used by your actions, or 您的操作使用的实用程序类,或者
  2. A base action class (meh), or 基本动作类别(meh),或
  3. A module included in your actions (meh). 动作中包含的模块(meh)。

I lean towards a utility class, because: 我倾向于实用程序类,因为:

  1. It's easy to instantiate or mock/stub it for testing, and 实例化或模拟/存根以进行测试很容易,并且
  2. It doesn't make the surface area of your action class any bigger 它不会使您的动作课程的表面积更大

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM