RoR-e

If you haven't seen The 15 minute E-Commerce Site CLICK HERE


I'm currently looking for Contract jobs, Contact Me if you are interested. Dave.

Use your Ruby API (Authlogic) David Henner Jan 30

3 comments Latest by Tanel Suurhans

This week I was psyched about creating a new plugin to extend authlogic. I've always had N+1 queries whenever I use current_user. I'd do crazy things like:

@current_user = User.find(current_user.id, 
                          :include => [:roles,
                                       :addresses]
                          )

I knew I was making 2 queries for current_user but that was better than having a N+1 queries. So this week I was determined to correct the problem. I started looking through the authlogic API and to my surprise the solution is already built into Authlogic.

Take a look at The API, with_scope is all you need. So now you could just do this in your application.rb.

def current_user_session
  if defined?(@current_user_session)
    return @current_user_session
  end

  @current_user_session = 
     UserSession.with_scope(
                  :find_options => {
                    :include => [:roles]}
                           ) do
       UserSession.find
  end
end

Now lets say in the addresses_controller.rb you need to include user.addresses. You can over-write the current_user_session method to:

private
def current_user_session
  if defined?(@current_user_session)
    return @current_user_session
  end

  @current_user_session = 
     UserSession.with_scope(
                  :find_options => {
                    :include => [:roles,
                                 :addresses]}
                           ) do
       UserSession.find
  end
end

def current_user
  return @current_user if defined?(@current_user)
  @current_user = current_user_session && 
                    current_user_session.record
end

I'm still looking for the optimal solutions for Rails 3 and authlogic. In rails 3, Arel doesn't make a query to the DB until you need the data. The problem with the standard Rails 2 solution comes because "find" actually makes a query to the DB. So this prevents chaining: @current_user.includes([:roles])

I'll follow up with this post as soon as I "find" a solution I like.

3 comments so far

Tanel Suurhans 31 Jan 11

Why not just straight up join the data you need, instead of including it via separate queries?

DRH 31 Jan 11

Tanel, I don't understand the question. current_user calls to the DB the first time it is called. Without the with_scope hook you need an extra query to get current_user.id.

Tanel Suurhans 14 Mar 11

Yeah sorry, my bad, i get what you're trying to do (seems i missed the User_Session_ part). What i generally meant was using something like .eager_load to eagerly load the needed association data in the same single query.

Comments are closed