Reputation: 452
I have a users table integrated with devise gem. The table has certain fields like current_sign_in_ip, last_sign_in_ip,current_sign_in_at, etc. Devise modifies these fields when the user logs in. I would like these fields to be moved to another table and populate them via devise or otherwise. Is there a way I can achieve this?
Upvotes: 3
Views: 799
Reputation: 452
Thanks for the response. It helped me to move in the correct direction. Let me share how I went about solving the problem I was facing.
As I wanted one-to-many relationship between users and user_logs table, I could not delegate the trackable methods to the UserLog model. Also, I wanted the user_logs table to be an insert-only table, hence I needed to override update_tracked_fields method of Devise Trackable module accordingly.
So :
I created a new user_logs table and UserLog model.
Overrid the update_tracked_fields method to actually insert a new row everytime in the user_logs table instead of updating users table.
Created getter methods for these trackable fields in User model that actually fetches required column value from the user_logs table. Like this :
self.try(:user_logs).last.try(:current_sign_in_ip)
Upvotes: 1
Reputation: 2267
There are two approaches to this answer:
The first (and easier, although not as pretty) option is to delegate the :trackable
methods to a second class (called UserDetail below). For example:
class UserDetail < ActiveRecord::Base
...
end
class User < ActiveRecord::Base
delegate :current_sign_in_ip, :last_sign_in_ip .... to: :user_detail
...
end
A cleaner option would be create a concern that avoids overriding Devise. You'd have to extend this on to your User
model:
module Trackable
def update_tracked_fields!(request)
old_current, new_current = user_detail.current_sign_in_at, Time.now.utc
user_detail.last_sign_in_at = old_current || new_current
user_detail.current_sign_in_at = new_current
old_current, new_current = self.current_sign_in_ip, request.ip
user_detail.last_sign_in_ip = old_current || new_current
user_detail.current_sign_in_ip = new_current
user_detail.sign_in_count ||= 0
user_detail.sign_in_count += 1
user_detail.save(:validate => false)
end
end
I got the second solution from Rodrigo Flores via this link. He reminds us to put record.update_tracked_fields!(warden.request)
on the Warden::Manager.after_set_user
block like they do here.
Upvotes: 5