Skip to content

Instantly share code, notes, and snippets.

@nickbarnwell
Created April 30, 2012 19:48
Show Gist options
  • Save nickbarnwell/2562109 to your computer and use it in GitHub Desktop.
Save nickbarnwell/2562109 to your computer and use it in GitHub Desktop.
Podio Hook Creation with Rails 3
class ApplicationController < ActionController::Base
def pw_podio_client
Podio.setup(PODIO_CLIENT_OPTIONS.merge(:oauth_token => password_token))
end
def password_token
@password_token ||= Podio::Client.new(PODIO_CLIENT_OPTIONS).authenticate_with_credentials(
PODIO_HOOK_OPTIONS[Rails.env][:username],
PODIO_HOOK_OPTIONS[Rails.env][:password]
)
end
end
#This is wicked hacky, but it does work
class CreateHookTable < ActiveRecord::Migration
def up
create_table :p_hooks do |t|
t.string :hookable_type
t.integer :hookable_id
t.integer :podio_id
t.string :podio_type, :default => 'Hook'
t.string :hook_type
t.boolean :validated, :default => false
t.timestamps
end
end
def down
drop_table :p_hooks
end
end
class Hook < Podio::Hook
end
class HooksController < ApplicationController
skip_before_filter :login_required, :only => :hook_call
skip_before_filter :init_podio_client, :only => :hook_call
before_filter :pw_podio_client, :only => :hook_call
protect_from_forgery :except => :hook_call
before_filter :find_hook
def hook_call
case params['type']
when 'hook.verify'
@hook.validate(params[:code])
when 'item.create'
@hook.hookable.item_created(params[:item_id].to_i)
when 'item.update'
@hook.hookable.item_updated(params[:item_id].to_i)
when 'item.delete'
@hook.hookable.item_deleted(params[:item_id].to_i)
end
render :text=>'', :status=>200
end
def validate
begin
@hook.verify()
rescue Podio::BadRequestError => e
handle_hook_exceptions e
end
redirect_to :back
end
private
def find_hook
@hook = PHook.find(params[:hook_id])
end
def handle_hook_exceptions(e)
if e.response_body['error'] == 'Hook is not waiting for verification'
@hook.force_validate
end
end
end
module PExceptions
class InvalidSpace < StandardError
end
class InvalidHookType < StandardError
end
class AlreadyConfiguredSpaceError < StandardError
end
end
class PHook < ActiveRecord::Base
before_destroy :destroy_podio_hook
belongs_to :hookable, :polymorphic => true
HOOK_TYPES = ['item.create', 'item.update', 'item.delete']
def self.create_for(ref_type, ref_id, type)
unless !HOOK_TYPES.include? type
hook = self.create
hook_id = Hook.create(ref_type, ref_id, {:type => type, :url => "http://#{Rails.application.config.app_url}/hooks/#{hook.id}"})
hook.update_attributes(:podio_id => hook_id, :hook_type => type)
return hook
else
raise InvalidHookType "That's not a valid hook"
end
end
def verify
Hook.verify(podio_id)
end
def validate(code)
res = Hook.validate(podio_id, code)
unless res.status != 204
update_attribute :validated, true
end
end
def verified?
validated == true
end
def force_validate
update_attribute :validated, true
end
private
def destroy_podio_hook
Hook.delete(podio_id)
end
end
module PApp #include in app model to be hooked
def create_hooks!
PHook::HOOK_TYPES.map do |type|
hook = PHook.create_for('app', podio_id, type)
hook.hookable = self
hook.save
end
end
end
@nickbarnwell
Copy link
Author

What I would suggest is breaking the validation of the hooks out of the request cycle by instead pushing them onto a queue as they come in and then having a worker handle it. As is you're prone to timeouts while waiting for them to complete, and additionally have to spin up that passworded Podio instance with some-regularity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment