I want to call a service to find location data every time the current_login_ip
on a user changes.
Now, one way to implement this would be to do
class User
#...
after_save :kickoff_job_to_find_location, if: :current_login_ip_changed?
end
However, I'd quite like to avoid adding an ActiveRecord callback if I can.
So, I went down the route of customizing UserSession with something like this:
class UserSession < Authlogic::Session::Base
before_create :set_update_location
def should_update_location?
@should_update_location
end
private
def set_update_location
@should_update_location ||= record && (record.current_login_ip != record.current_login_ip_was)
end
end
Then, from my controller, I could call user_session.should_update_location?
and perform some logic.
The issue however, is that (as far as I can tell from testing) all the callbacks are copied across into the User
model, so that if you create a user model then the before_create defined above in UserSession is also executed. This happens even if you are not creating a UserSession. That means that my @should_update_location
was called twice (once when the user was created, once when the session was created) but by the time the session was created, the current_login_ip
had been set, so my should_update_location?
returned false.
I could work around it by simply calling out to my method from within the UserSession itself like this:
class UserSession < Authlogic::Session::Base
before_create :update_location_if_new_or_changed
private
def update_location_if_new_or_changed
if record && (!record.persisted? || (record.current_login_ip != record.current_login_ip_was))
puts "calling set_update_location"
end
end
end
But that doesn't seem any nicer. So I have currently given up, and implemented the after_save
hook on User.
What is the right way to perform this sort of "if the current_login_ip changes" behaviour? Is it OK, in this instance, to actually have a callback on the User model? It's currently looking the nicest way to me.