Devise fields inside a password table
Is that possible to setup Devise gem easily with every of its fields inside a passwords table, which is mapped with a Password model belonging to a User model (having just an email field)?
In other words, here is a draw of my wanted model design:
+-------+ | User | +-------+ | email | +-------+ ^ (have one) | | (belongs to) +------------------------+ | Password | +------------------------+ | encrypted_password | | reset_password_token | | reset_password_sent_at | | sign_in_count | | ... | +------------------------+
The Devise wiki is very complete, but there's not any info about this.
Yes, there is a workaround that consists in overriding Devise internal methods (which is a not recommended thing).
However, I haven't tested it well (I only created a user and tried to login), this can introduce some bugs and inexpected behaviour in Devise. So, please, ensure your application is well tested before this code is shipped to production.
The solution to the database authenticatable module consists in:
Write the migration
class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| t.string :email t.timestamps end create_table :passwords, :force => true do |t| t.integer :user_id t.string :encrypted_password, :null => false, :default => "" end end end
create a delegate that points to password_record#encrypted_password.
- add a accepts_nested_attributes_for to password_record
- create a setter for the encrypted_password attribute (Devise uses this)
Your models should be like this:
class User < ActiveRecord::Base devise :database_authenticatable has_one :password_record, :class_name => "Password", :foreign_key => "user_id" delegate :encrypted_password, :to => :password_record accepts_nested_attributes_for :password_record def encrypted_password=(encrypted_password) self.password_record.encrypted_password = encrypted_password end attr_accessible :email, :password, :password_confirmation, :remember_me end class Password < ActiveRecord::Base belongs_to :user end
I created a user, using this:
x = User.new x.password_record = Password.new x.password = "123456" x.email = "firstname.lastname@example.org" x.save
I tested the sign_in action and it worked.
You can create using a sign_up form with nested attributes. To check how to do the same things for other modules, take a look at the Devise source code () and see what attributes it uses and how it works (https://github.com/plataformatec/devise/tree/master/lib/devise/models).