Wrapping Rails Session Hash: Follow Up
Matt Swasey, Former Viget
The other week I wrote about wrapping your Rails session variables in current_object methods. There is, however, a performance related bug in line 5 of the code I posted:
class ApplicationController < ActionController::Base helper_method :current_account def current_account @current_account ||= Account.find_by_id(session[:current_account_id]) end def current_account=(account) session[:current_account_id] = account.try(:id) end end
If session[:current_account_id] is nil, current_account will make a useless database query each time it is called. This would happen if you are calling current_account on a public page while a user has yet to log in.
We can fix this in the following way:
... def current_account if session[:current_account_id] @current_account ||= Account.find_by_id(session[:current_account_id]) end end ...
The above code will only evaluate @current_account if session[:current_account_id] has been set, otherwise it will return nil without hitting the database. Once session[:current_account_id] is set, it will hit the database a single time, memoize the result in @current_account, and return @current_account for the duration of the Rails request cycle. This should help take some load off the database.
If anyone has an even simpler solution, please let me know in the comments!