I understand that the Rails observer should not have direct access to the controller. This makes sense; there is no information about the context from which the observer will be called. However, I have a case that, it seems to me, deserves an indirect connection between them, and I wonder how to achieve it.
Logging and recording analytics events
I would like to use an observer to trigger certain events in Google Analytics. The way that currently works is that the application controller has a method that logs the event, and then the application.html.erb
template prints the appropriate javascript on the page:
class ApplicationController < ActionController::Base def logGAEvent category, action, opt_hash={} event = { :category => category, :action => action, :label => opt_hash[:label], :value => opt_hash[:value]} (session[:ga_events] ||= []) << event end end
Application.html.erb
<html> <head> ... <script type="text/javascript"> <%= print_ga_events_js %> </script> </head> ... </html>
Event example:
class UsersController < ApplicationController ... def create ... if @new_user logGAEvent('user', 'signup') end end end
Why I would like to communicate between the observer and the controller
Currently, the logGAEvent method is called in controllers after certain noteworthy events (someone signs up, creates a new profile, etc.).
It would be much better to draw most of these events in an observer. This will remove the controller and also make tracking less ad-hoc. However, once they enter the observer, there should still be a way for the template to access the observer data and print it.
What i would like to do
Since the observer does not need to know about the controller, I would like to write these events to a one-time buffer so that they are discarded at the end of each call, but they are also available to the controller for writing to the document:
class UserObserver < ActiveRecord::Observer after_create user
application.html.erb (using buffer)
Application.html.erb
<html> <head> ... <script type="text/javascript"> <%= print_ga_events_js(request.buffer.ga_events) %> </script> </head> ... </html>
Is it possible? This is not like an unreasonable design template for me, and it will make the application cleaner.