Every time I hit an authenticated page, I notice devise issuing an SQL statement :
User Load (0.2ms) SELECT users
.* FROM users
WHERE (users
.id
= 1) LIMIT 1
(I'm using Rails 3 btw .. so cache_money seems out as a solution and despite a lot of searching I've found no substitute).
I tried many overrides in the user model and only find_by_sql seems called. Which gets passed a string of the entire SQL statement. Something intuitive like find_by_id or find doesn't seem to get called. I 'can' override this method and glean the user-id and do a reasonable cache system from that - but that's quite ugly.
I also tried overriding authenticate_user which I can intercept one SQL attempt but then calls to current_user seems to try it again.
Simply, my user objects change rarely and its a sad state to keep hitting the db for this instead of a memcache solution. (assume that I'm willing to accept all responsibility for invalidating said cache with :after_save as part but not all of that solution)
The following code will cache the user by its id and invalidate the cache after each modification.
class User < ActiveRecord::Base
after_save :invalidate_cache
def self.serialize_from_session(key, salt)
single_key = key.is_a?(Array) ? key.first : key
user = Rails.cache.fetch("user:#{single_key}") do
User.where(:id => single_key).entries.first
end
# validate user against stored salt in the session
return user if user && user.authenticatable_salt == salt
# fallback to devise default method if user is blank or invalid
super
end
private
def invalidate_cache
Rails.cache.delete("user:#{id}")
end
end
WARNING: There's most likely a better/smarter way to do this.
I chased this problem down a few months back. I found -- or at least, I think I found -- where Devise loads the user object here: https://github.com/plataformatec/devise/blob/master/lib/devise/rails/warden_compat.rb#L31
I created a monkey patch for that deserialized method in /initializers/warden.rb to do a cache fetch instead of get. It felt dirty and wrong, but it worked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With