简体   繁体   中英

authlogic current_user tracking

I use authlogic for authentication and paperclip for handling user's profile picture attachments.

I use the following method to get the current_user

    def current_user_session
        return @current_user_session if defined?
(@current_user_session)
        @current_user_session = UserSession.find
    end

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

and the following after_save callback to regenerate the profile image if the image has changed.

   after_save do |user|
        if user.image_changed?
            Delayed::Job.enqueue ImageJob.new(user.id)
        end
    end

The current_user method issues a UserSession.find call and Looking at the docs it seems UserSession.tries to Log the user in, which results in an update to certain fields (updated_at, token etc. but not the profile image), which results in a save of the user record, which in my case results in after_save callbacks firing. This after save callback checks to see if there has been a change to user's profile image, which unnecessarily consumes time.

Now this is fine if the user indeed is trying to update profile, but since I use current_user in many different places within my app, this callback is getting fired (and its an expensive call), for no reason.

I understand this isn't exactly authlogic issue, but is there anyway I can avoid this, ie either not update the user record or somehow differentiate between what is a profile update and what is an update resulting from this UserSession.find login?

Thanks

Here is the solution that worked based on bjg's suggestion.

before_save :check_what_changed

def check_what_changed if self.changed.sort == ["last_request_at", "perishable_token"] self.skip_profile_update = true return true else self.skip_profile_update = false return true end end

Update #2 I take that back that didn't work, but it's not really a problem with this solution, for some reason paperclip tries to save the attachments even before the after_save callback. This is likely a paperclip issue, no idea..

In a before_save callback, you could differentiate between a real profile change and the Authlogic related changes ( last_request_at and updated_at attributes) using the Rails built-in dirty objects tracking facility. Something along these lines

attr_accessor :skip_profile_update

before_save do |model|
  model.skip_profile_update = (model.changed.sort == ['last_request_at', 'updated_at'])
end

after_save do |model|
  unless model.skip_profile_update
    # etc
  end
end

I was having a problem with bjg's solution because sometimes I'd ONLY get 'last_request_at' and not 'updated_at' and so skip_profile_update would be false.

I changed it to this which is a whitelisted list of fields which SHOULD trigger the after_save, rather than the blacklist method. It could be easily changed to blacklist by changing the array comparison method . I also found it necessary to include all the 'true's because I was getting those dreaded "ActiveRecord record not saved" errors otherwise.

attr_accessor :record_activity

before_save do |user|
    user.record_activity = (user.changed & ['email', 'birthday', 'zip', 'gender']).present?
    true
  end

  after_update do |user|
    if user.record_activity
     user.send(:record_update_activity)
     true
    end
    true
  end 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM