Reputation: 1182
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. 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? It doesn't feel right to be repeating the same code again and again each time I have to authenticate and connect.
Upvotes: 0
Views: 121
Reputation: 18783
To build on @Dave Newton's answer:
You would create a "provider" class that marries an object factory to some configuration:
File: 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
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.
Also @Gareth Burrows comment on where to put and name the class, I think this would fit just fine in the lib/ directory. See the edits to the post for specifics.
Upvotes: 1
Reputation: 2576
You can create a regular ruby class in the models folder called Xero or something and do this code in the initializer.
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. xero_gateway.rb
And put the initialization code in there. This way it will be parsed only on application startup.
Upvotes: 0
Reputation: 160181
You could put it just about anywhere, including:
I lean towards a utility class, because:
Upvotes: 0