Closeio::Rails
A handy wrapper around the closeio
gem to make Rails integration a little easier.
Models
There are 5 models defined in this gem. The aim is to have a DSL a little more like the familiar ActiveRecord one.
Closeio::Rails::Base
All the models inherit from Closeio::Rails::Base
, which has a couple of mixins:
Closeio::Rails::Attributes
Make the model respond to attributes()
- it returns a hash, like ActiveRecord
Closeio::Rails::DateCoercion
Parse the creation and update dates into datetime objects, and add created_at()
and updated_at()
methods which are in line with Rails norms.
Closeio::Rails::Lead
This is where most of the action happens. Leads have contacts, of type Closeio::Rails::Contact
Closeio::Rails::Contact
A contact entry in Close.io. Not accessible on its own; always created after a call to `Closeio::Lead
Closeio::Rails::CustomField
It's often useful to create and update custom fields in Close.io programatically - changing the values of select lists and similar.
Closeio::Rails::Note
This is a very lightweight wrapper around Close::Client#create_note.
Closeio::Rails::Webhook
A similarly lightweight wrapper around Closeio::Client#create_webhook
Configuration
Configure the gem in an initializer like this:
Rails.application.config.to_prepare do
Closeio::Rails.configure do |config|
config.api_key = 'your key' #or put in Rails secrets, or somewhere else
config.verbose = false
end
end
You can add your own methods into the Closeio::Rails models by including them in your initializer like this:
# Leadmethods and ContactMethods are modules in your Rails project. Obviously they could be namespaced, etc.
Closeio::Rails::Lead.send(:include, LeadMethods)
Closeio::Rails::Contact.send(:prepend, ContactMethods)
You might want to add actions to the webhooks controller, too. Sometimes we use this on applications with some sort of authentication defined in ApplicationController
, which needs to be ignored on the webhooks controller:
Closeio::Rails::WebhooksController.send(:skip_before_action, :authenticate_user!)
Closeio::Rails::WebhooksController.send(:skip_after_action, :verify_authorized)
Mountable webhooks controller
It's useful to receive webhooks from Close.io. You have to drop a note to their support team to set it up but it's very quick.
Mount your route like this:
mount Closeio::Rails::Engine => "/closeio" #this can be any path you like
That'll give you the following routes:
debug_webhooks GET /webhooks/debug(.:format) closeio/rails/webhooks#debug {:format=>:json}
webhooks POST /webhooks(.:format) closeio/rails/webhooks#create {:format=>:json}
The debug_webhooks_path
only works in development. It just sanity-checks that you've got ot mounted properly :)
Adding webhooks - rake tasks
There are 3 rake tasks which are available to use in your application:
rake closeio:rails:list_webhooks
Give you a list of webhooks with their ID and endpoint
rake closeio:rails:create_lead_webhook[endpoint_url]
Sets up a webhook to track leads. Pass in an endpoint URL.
rake closeio:rails:destroy_webhook[id]
Pass in the ID you got from rake closeio:rails:list_webhooks
to destroy a webhook and no longer receive messages to that endpoint.
Adding other webhooks
You can add other webhooks with different subscriptions by calling Close::Rails::Webhook.create(params)
where params is a hash which looks like this:
Closeio::Rails::Webhook.create({
url: url,
events: [
{
object_type: 'lead',
action: 'created'
},
{
object_type: 'lead',
action: 'updated'
},
{
object_type: 'lead',
action: 'deleted'
},
{
object_type: 'lead',
action: 'merged'
}
]
})
end
See the docs for more details.
Consuming webhooks in your application
The controller doesn't do anything when it receives a webhook - instead it uses ActiveSupport::Notifications to allow you to subscribe to the raised events to do what you need to. Here's an example:
ActiveSupport::Notifications.subscribe(/closeio\.(create|update|delete)/) do |name, start, finish, id, payload|
if payload[:model] == 'lead'
SomeLeadRelatedJob.perform_later payload[:data][:id]
end
end
Check the Close.io docs to get a sense of what you get in the payload - one important thing to nose is that when you get a 'closeio.merge' notification, you don't get an ID, you'll get a :source_id
and a :destination_id
.
Importantly, if you're using ActiveJob with the inline
strategy you'll need to make sure you rescue from any failures, or the controller won't return a 200 OK and Close.io will keep retrying.
Contributing
Pull requests welcome. The usual drill: fork, commit changes, PR.
Licence
MIT - see LICENCE.txt.