I am getting the following error when I try to sign in in my rails app. I used devise for authentication. My error is
NoMethodError in Devise::SessionsController#create
undefined method `current_sign_in_at'
My user model is
models/user.rb
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
attr_accessible :admin,:first_name, :last_name, :profile_name, :college_name, :email, :password, :password_confirmation, :remember_me, :provider, :uid
def admin?
end
def self.find_for_facebook_oauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
#user.name = auth.info.name # assuming the user model has a name
#user.image = auth.info.image # assuming the user model has an image
user.save!
end
end
end
My schema is
db/schema.rb
ActiveRecord::Schema.define(:version => 20140126101946) do
create_table "levels", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "profile_name"
t.string "college_name"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "provider"
t.string "uid"
t.boolean "admin", :default => false
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
end
The code in my devise_create_users.rb is
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.string :profile_name
t.string :college_name
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
My trackable was commented and I removed the comments and then ran rake db:migrate but nothing happened. Now I cannot remove trackable as I need it. What I need is that somehow I can keep my devise as it is and also add trackable to it in such a way that it gets added to the schema.rb as well.
To add new columns to existing tables, simply updating already run migration is not going to work as the schema is at a later version than your existing migration's version. If you wish to modify the existing migration, you could run a down migration with:
rake db:migrate:down VERSION=20140126101944 # use version of the user migration
Then modify the migration adding the new columns as you've already done, then run up migration using:
rake db:migrate:up VERSION=20140126101944 # use version of the user migration
A better approach is to add a new migration with the change if your application is already in production.
To add the trackable columns to existing users table:
class AddTrackableColumnsToUser < ActiveRecord::Migration
def change
change_table :users do |t|
## Trackable
t.add_column :sign_in_count, :integer, :default => 0
t.add_column :current_sign_in_at, :datetime
t.add_column :last_sign_in_at, :datetime
t.add_column :current_sign_in_ip, :string
t.add_column :last_sign_in_ip, :string
end
end
end
Then run db:migrate:
rake db:migrate
In your models/user.rb
Change
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :validatable, :omniauthable
to
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:validatable, :omniauthable
i.e. remove :trackable
Related
I have been trying to add user login / authentication to my RoR site. I am using Devise.
Things work fine in my dev instance (I use Cloud9, in case useful).
However when I push to Heroku / production, for any page related to the user functionality (e.g. User Sign up, User login, or a page which checks if the user is logged in), it errors out. All Heroku gives me is:
NoMethodError (undefined method `to_sym' for nil:NilClass):
Just looking for some ideas on what could be happening?
user.rb:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
enum role: [:user, :business, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
DeviseCreateUsers migration:
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.integer :role, default: 0
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
Many thanks!
I am new to rails+angular. For my app, I want to lock out user after 5 failed password attempts. I decided to follow this:
How to make Devise lockable with number of failed attempts
But when I try logging in after 5 failed attempts, it lets me through
I added the :locked module to my user.rb (shown below) file so that the locked feature appears in devise.rb
User.rb
class User < ActiveRecord::Base
include TokenAuthenticatable
TYPE = {
:admin => 1,
:member => 2
}
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable, :token_authenticatable,
:timeoutable, :lockable ##this was added
has_and_belongs_to_many :clients
end
In my migrations then, I un-commented out the lockable part of it :
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.string :type
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
end
To troubleshoot this, I also tried adding :locked, :failed_attempts => 5and uncommented out all the lockable features in initializer/devise. I am unsure on how to proceed - help would be appreciated.
This is my user model called "user.rb" and I want that people can sign in with their Facebook account and transfer their profile picture to my website. The problem is that it keeps saying that "user.image" in the "profile_picture" variable is undefined. Ruby stores the image with the paperclip gem.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable
validates :fullname, presence: true, length: {in: 2..50}
def self.from_omniauth(auth)
user = User.where(email: auth.info.email).first
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.fullname = auth.info.name
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.image = auth.info.image
user.password = Devise.friendly_token[0,20]
end
end
end
def profile_picture
if user.image
user.image
else
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" }, :default_url => "/images/:style/missing.jpg"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end
end
end
In my html.erb file I call the image method with:
<%= image_tag current_user.avatar.url(:thumb) %>
I know I will have to change it to:
<%= image_tag current_user.profile_picture %>
Here is my schema.rb file:
ActiveRecord::Schema.define(version: 20150927111830) do
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "fullname"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "provider"
t.string "uid"
t.string "image"
end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
user in the profile_picture method is out of scope. Whenever you declare a local variable within your method (e.g user), this will only be available inside the scope of that method.
current_user is an instance of User so if you want the image of that user you can simply call in your image_tag:
<%= image_tag(current_user.image) %>
I am using devise for authentication in my rails app.
I keep getting different errors like "undefined method XXXX for User:class".
Looking for some help to setup devise correctly.
I have the module database_authenticable setup for Users and I hit the error:
undefined method `params_authenticatable?' for User:Class
Its comming from the following devise code in lib/devise/strategies/authenticatable.rb
def params_authenticatable?
mapping.to.params_authenticatable?(authenticatable_name)
end
Here are my devise settings:
class User < ActiveRecord::Base
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :trackable, :validatable , :omniauthable, :omniauth_providers => [:linkedin]
.
.
end
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
end
Mu authentication requirements are straightforward and I want to use Linkedin authentication and eventually allowing other omni auths as well.
I am wondering if I should use socery or something else for simple authentication
Thanks !
I am using Rails4.0
I'm absolutely new to Rails, I nearly do not know what I am doing. But. The problem is: signing up new user with Devise results in:
SQLite3::ConstraintException: column email is not unique:
INSERT INTO "users" ("created_at","encrypted_password", "name", "updated_at")
VALUES (?, ?, ?, ?)
And the request parameters:
{"utf8"=>"✓",
"authenticity_token"=>"1bgk4ovS3JitphVkIvcCZi3ex8QsBq4eEf6ZihQLiHg=",
"user"=>{"name"=>"Someone",
"email"=>"8#prosto.me",
"password"=>"[FILTERED]"},
"commit"=>"Sign up"}
User model:
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;
end
DB migration:
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
change_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :name, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
# Uncomment below if timestamps were not included in your original model.
# t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :name, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
def self.down
# By default, we don't want to make any assumption about how to roll back a migration when your
# model already existed. Please edit below which fields you would like to remove in this migration.
end
end
Please tell me if I need to provide any other code.
And thank you for all your help in advance.
Update with DB schema:
ActiveRecord::Schema.define(version: 20131012114812) do
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Update 2: And there is also a problem with authentication. Devise tells 'Invalid email or password' for any previously successfully signed up user in attempt to login.
SQLite is telling you that it's trying to create a new record, where one of the values will be an email, but there is already an existing record with that email.
An easy way to read your database records is query the DB in a terminal window:
$ rails console
$ User.all
If you want to see your test DB, which will be loaded with your fixtures:
$ rails console -e=test
$ User.all
Look for records that have the same email of the one you're trying to create.
If this is your first time using Devise, you should check your fixtures. Devise currently defaults to two fixtures that have no attributes. If you're running in a test environment then those fixtures will be loaded into the test DB as a two records with nil values for email, which are duplicate email values. Fixtures like the ones below will get you passed your error message.
file: app/test/fixtures/users.yml
one:
email: user#example.com
encrypted_password: password1
two:
email: user2#example.com
encrypted_password: password2
Do you have any other "email" columns in that database?
Perhaps you already had a "users" table, where the email column has been replicated with Devise. It would be helpful if you could show us which columns your table has :)
Try adding a uniqueness validation to your User model:
validates_uniqueness_of :email, :allow_blank => true
This will re-render your user creation form instead of causing an error.