Callback hooks

Callback hooks provide a mechanism to change the behavior and presentation of FatFreeCRM without having to modify the application code itself.

Types of hooks

Controller Hooks

Controller hooks let you change what data is getting passed along to the views, and modify behavior during an action should you need to. This is mainly accomplished through a few defined hooks on each main model in FatFreeCRM

before_filter hooks

app_before_filter home_before_filter

after_filter hooks

app_after_filter

get_* hooks

Things like get_leads and get_contacts.

Let’s look at the leads controller /app/controllers/leads_controller.rb and the get_leads private method that does the actually fetching of lead records:

I’ve editted a bit for readability.


def get_leads(options = { :page => nil, :query => nil })

    # Call :get_leads hook and return its output if any.
    leads = hook(:get_leads, self, :records => records, :pages => pages)
    return leads.last unless leads.empty?

    # Default processing if no :get_leads hooks are present.
    if session[:filter_by_lead_status]
      filtered = session[:filter_by_lead_status].split(",")
      current_query.blank? ? Lead.my(records).only(filtered) : Lead.my(records).only(filtered).search(current_query)
    else
      current_query.blank? ? Lead.my(records) : Lead.my(records).search(current_query)
    end.paginate(pages)
  end

So here, the controller is actually going to call any hooks that define get_leads and use that as the data to display rather than fetch it directly from the database.

View Hooks

View hooks give you an easy way to get something displayed on a FatFreeCRM view.

For example, on the contact partial: /app/views/contacts/_contact.html.haml you can see at the bottom something like this:


        = t(:added_ago, time_ago_in_words(contact.created_at))
      = hook(:contact_bottom, self, :contact => contact)

The interesting bit is the = hook(:contact_bottom, self, :contact => contact)

If you wanted to add something to the bottom of the contact partial you’d need to create a hook method contact_bottom. The sample_crm_plugin has examples of this.

Here’s a modified example to follow through with contact:


class ContactCallback < FatFreeCRM::Callback::Base
  def show_contact_bottom(view, context = {})
    view.logger.info "view: " + view.class.to_s
    view.logger.info "context: #{context.inspect}"
    # render the contents of my own partial, passing it the contact (we got this from the hook above, :contact => contact)
    view.controller.send(:render_to_string, :partial => "my_super_stuff/extra_data_partial", :locals => { :contact => contact })
  end
end

List of Hooks

You can get a list of all the hooks in FatFreeCRM by doing something like this grep -ir hook\( app/ at the root of your FatFreeCRM project.

Controller Hooks


 grep -ir hook\( app | grep -v haml
app/controllers/accounts_controller.rb:    accounts = hook(:get_accounts, self, :records => records, :pages => pages)
app/controllers/application_controller.rb:  before_filter "hook(:app_before_filter, self)"
app/controllers/application_controller.rb:  after_filter "hook(:app_after_filter, self)"
app/controllers/application_controller.rb:    @auto_complete = hook(:auto_complete, self, :query => @query, :user => @current_user)
app/controllers/campaigns_controller.rb:    campaigns = hook(:get_campaigns, self, :records => records, :pages => pages)
app/controllers/contacts_controller.rb:    contacts = hook(:get_contacts, self, :records => records, :pages => pages)
app/controllers/home_controller.rb:  before_filter "hook(:home_before_filter, self, :amazing => true)"
app/controllers/home_controller.rb:    hook(:home_controller, self, :params => "it works!")
app/controllers/leads_controller.rb:    leads = hook(:get_leads, self, :records => records, :pages => pages)
app/controllers/opportunities_controller.rb:    opportunities = hook(:get_opportunities, self, :records => records, :pages => pages)
 

View Hooks


grep -ir hook\( app | grep haml
app/views/accounts/_account.html.haml:      = hook(:account_bottom, self, :account => account)
app/views/accounts/_sidebar_index.html.haml:  = hook(:index_account_sidebar_bottom, self)
app/views/accounts/_sidebar_show.html.haml:  = hook(:show_account_sidebar_bottom, self, :account => @account)
app/views/accounts/_top_section.html.haml:    = hook(:account_top_section_bottom, self, :f => f)
app/views/accounts/show.html.haml:= hook(:show_account_bottom, self)
app/views/campaigns/_campaign.html.haml:      = hook(:campaign_bottom, self, :campaign => campaign)
app/views/campaigns/_sidebar_index.html.haml:  = hook(:index_campaign_sidebar_bottom, self)
app/views/campaigns/_sidebar_show.html.haml:  = hook(:show_campaign_sidebar_bottom, self, :campaign => @campaign)
app/views/campaigns/_top_section.html.haml:    = hook(:campaign_top_section_bottom, self, :f => f)
app/views/campaigns/show.html.haml:= hook(:show_campaign_bottom, self)
app/views/common/_inline_styles.html.haml:  = hook(:inline_styles, self)
app/views/contacts/_contact.html.haml:      = hook(:contact_bottom, self, :contact => contact)
app/views/contacts/_sidebar_index.html.haml:  = hook(:index_contact_sidebar_bottom, self)
app/views/contacts/_sidebar_show.html.haml:  = hook(:show_contact_sidebar_bottom, self, :contact => @contact)
app/views/contacts/_top_section.html.haml:      = hook(:contact_top_section_bottom, self, :f => f)
app/views/contacts/show.html.haml:= hook(:show_contact_bottom, self, :contact => @contact)
app/views/home/index.html.haml:  = hook(:home_view, self, :hello => "world!", :welcome => "home")
app/views/layouts/application.html.haml:      = hook(:javascript_epilogue, self)
app/views/leads/_lead.html.haml:      = hook(:lead_bottom, self, :lead => lead)
app/views/leads/_sidebar_index.html.haml:  = hook(:index_lead_sidebar_bottom, self)
app/views/leads/_sidebar_show.html.haml:  = hook(:show_lead_sidebar_bottom, self, :lead => @lead)
app/views/leads/_top_section.html.haml:    = hook(:lead_top_section_bottom, self, :f => f)
app/views/leads/show.html.haml:= hook(:show_lead_bottom, self)
app/views/opportunities/_opportunity.html.haml:      = hook(:opportunity_bottom, self, :opportunity => opportunity)
app/views/opportunities/_sidebar_index.html.haml:  = hook(:index_opportunity_sidebar_bottom, self)
app/views/opportunities/_sidebar_show.html.haml:  = hook(:show_opportunity_sidebar_bottom, self, :opportunity => @opportunity)
app/views/opportunities/_top_section.html.haml:      = hook(:opportunity_top_section_bottom, self, :f => f)
app/views/opportunities/show.html.haml:= hook(:show_opportunity_bottom, self)
app/views/tasks/_top_section.html.haml:    = hook(:task_top_section_bottom, self, :f => f)
app/views/users/_profile.html.haml:  = hook(:profile_user_bottom, self)
app/views/users/show.html.haml:= hook(:show_user_bottom, self)