How To Recover a Password with Devise ( Ruby on Rails) - ruby-on-rails

I'm trying to recover a user's password with devise, but it generates the following error
undefined method `reset_password_sent_at=' for #<User:0x007fb78cfafb68>
Can anyone help me with this, since I'm new to Ruby on Rails?
What is the best way to recover a password and email the user using Devise? Thank you very much...
I'm use devise (2.2.3)
User.rb
require 'digest/md5'
class User < ActiveRecord::Base
# Setup accessible (or protected) attributes for your model
belongs_to :shop
before_create :compute_email_md5
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:token_authenticatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email,
:email_md5,
:password,
:password_confirmation,
:shop_id,
:role,
:terms,
:name,
:notify_on_order_received
validates :terms, :acceptance => true, :on => :create
end
THE SOLUTION IS
add reset_password_sent_at column to user table

As you've discovered, passord recovery requires that the model have a reset_password_sent_at column. Adding it via migration should solve this problem.
As for the reason this is happening, I'm guessing you added password recovery (the :recoverable module) after initially generating your Devise-enabled model (User). That's why Devise's generator didn't create that column for you.

Related

Get variable from another table in ROR models

I am trying to get a user who has not filled out their profile to redirect to the edit page.
I have two tables - Users (Devise handles) and Profiles.
Profiles has a row called profile_complete
In my user model I am trying to define a method called profile_complete which takes the boolean of profiles_complete and passes it back.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :profiles, :dependent => :destroy
def profile_complete?
self.profile.profile_complete == true
end
end
But cannot seem to figure out what the line in the profile_complete method is. I have got the other bits working in the correct place but cant get this variable across Any help? Cheers :)
def profile_complete?
self.attributes.values.include?(nil) ? false : true
end

Don't receive callback with devise_invitable

I'm using devise_invitable to allow users to invite each other. I want to set values for the user when the invite is created or when it's accepted. One approach is here
Using devise_invitable for adding Users to a Group in Ruby on Rails?
but this seems overkill. The callbacks look like a perfect solution, but they don't seem to fire during my Rspec tests.
Here is the user model:
class User < ActiveRecord::Base
belongs_to :company
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :company
validates :company, :presence => true
after_invitation_accepted :email_invited_by
before_invitation_accepted :email_invited_by
private
def email_invited_by
# This is NEVER executed during tests, even when an invite is successfully accepted
puts "Callback worked"
end
end
Any clues about where to look would be appreciated. I find the devise_invitable documentation a bit opaque.
Thanks!
For those still looking for an answer here is what worked for me.
The issue is not with validations since in devise_invitable there is a config to validate on invite and it defaults to false:
# Flag that force a record to be valid before being actually invited
# Default: false
# config.validate_on_invite = true
So my solution is to use the callback provided by devise_invitable:
after_invitation_accepted :create_profile
Do note that this needs to be below devise :invitable
devise_invitable callbacks will be fired if the user has been really invited (i.e. the object is persisted and there's an invitation token set) and the object (user's object) has no validation errors. That said, I see that you're validating presence of company without any conditions, which, I think, could be causing validation errors.
If that's the case, you can add a condition like this
validates :company, :presence => true, :if => Proc.new { self.invitation_token.nil? }
so it won't cause validation errors and fire the callbacks.

How to Create a User Profile in Rails?

I am using Devise for user registration and authentication but want to have user profiles too, for example /user/john-doe with all the fields like Company Name, Phone Number etc which the person can add.
Is there any Rails way to get it done out of the box? any gem for this? if not, can someone give me some direction on how to do it?
There is no gem to add company name, phone etc (at least I know :)), but normally what I do is,
I add the above columns to table, via a migration
Ex: add_column :users, :company_name, :string
then I update the model accordingly
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, *:company_name*
end
then I run this command to copy the devise views
rails generate devise:views
then I update the corresponding view with new text_boxes etc..
HTH

Devise - login from two model

I have two user models, first is from remote database as legacy and for internal company purposes. (Employee logins). Second is our project for public registration and sign in but I want one login form. I have searching long time, but some solutions are confusing for me.
First legacy looks like (only for reading and authentication):
class CrmUser < ActiveRecord::Base
require Rails.root.join('lib', 'devise', 'encryptors', 'sha1')
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable, :rememberable, and :omniauthable
establish_connection "crm_data"
set_table_name :users
devise :database_authenticatable, :encryptable, :authentication_keys => [:login]
alias_attribute :encrypted_password, :crypted_password
alias_attribute :password_salt, :salt
# Setup accessible (or protected) attributes for your model
attr_accessible :login, :password, :password_confirmation, :remember_me, :role_id, :first_name, :last_name
And second, for public and registration:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable, :rememberable, and :omniauthable
devise :database_authenticatable, :registerable, :authentication_keys => [:login]
alias_attribute :login, :email
# Setup accessible (or protected) attributes for your model
attr_accessible :login, :password, :password_confirmation, :remember_me, :role_id, :first_name, :last_name
Now I don't know how to do that User controller try to authentication from first model, and when user doesn't exists, go to second model and try it again.
Using:
Rails 3.1
Devise 1.4.3
EDIT:
In wiki of Devise is something about multiple model, but I'm little bit confused, there are not example more complex.
Thank you.
Regards, Rado
You should monkeypatch find_for_authentication method from devise/models/authenticatable.rb
module Devise
module Models
module Authenticatable
def find_for_authentication(conditions)
#put your authentication logic here
end
end
end
end
About authentication logic:
Using two models for authentication in your case it's realy bad idea. How do u want build relations with two users models? It's a lot of unnecessary code.
Correct way of resolving your problem is make some synchronization between yours tables.
Try to authenticate user with base User model.
If user credentials was wrong - try to authenticate him with CrmUser model.
If authentication with CrmUser was OK add him to users table if he doesn't exists there already.
Return User's model object.

Model attribute is not being set when using devise?

I used devise to create a user model. It contains all the default stuff from devise as well as 2 more database columns: first_name and last_name. Pretty simple stuff.
I am coding some tests to try it out:
#user = User.new(:first_name => "Ken", :email => 'myemail#gmail.com', :password => 'apassword')
#user.valid?
puts "user's first name: #{#user.first_name}"
puts #user.errors
In my model, I have this:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
validates_presence_of :first_name
end
For some reason, "first_name" is not getting set when I pass it in the constructor. The password and email are getting set, but not first_name.
Does anyone know why? I have played a bit with rails, and it works in other models. Why not with devise?
In your User model, write this:
attr_accessible :first_name, :last_name
and you are good to go.

Resources