I was following this how-to on How To: Allow users to sign in using their username or email address and did all the steps detailed there but when I try to register via the registrations/new.html.erb form I get this error:
Email can't be blank
In my model I have:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :username, :email, :password, :password_confirmation, :remember_me
attr_accessor :login
attr_accessible :login
and
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
any advice with this problem?
======= UPDATE
I found something here ■[rails]How to use Devise and Rails , without EMail here it is something like:
# Email is not required
def email_required?
false
end
With that added in my model I can create a record with username and leaving the email field blank, but when I try to create a second record without email the database rises an error:
Mysql2::Error: Duplicate entry '' for key 'index_parents_on_email':...
Should I use this, remove the index from my table in the database, and just validate the username in the model? because I don't really need the email field on that model.
Update
Asiniy's answer below actually works like a charm (:
Original (who knew?)
Your problem is the index on the mysql table, you might remove it from your migrations, but I'm not sure that will solve your problem. Not using the email in Devise is tricky, I would suggest a workaround like a fake email out of the username, something like this
"#{user.username}#fake.me"
It's not very clean but I see devise doing something similar for passwords when you use omniauth.
Rails 4 and Strong Parameters
I got into this problem for username in rails 4, and I had to configure the permitted parameters as below for sign_up:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit :username, :email, :password, :password_confirmation
end
end
end
This is described in Devise Doc
Normal solution
class User < AR::Base
devise_for tralala
def email_required?
false
end
end
Please refer to the https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L29
Related
I'm new to Rails 5 and I'm trying to model the following scenario using Devise and CanCanCan: a store application.
Relevant figures are: Admin, StoreManager, StoreOfficer, Customer, Technician.
Admin creates StoreManager.
StoreOfficer can create Customer's information to register new Customers.
StoreOfficer can see the complete list of all Customers with relative information
StoreOfficer can see the complete list of all Technicians with relative information
StoreManager can see the complete list of all StoreOfficers with relative information
StoreManager can enable StoreOfficers to use the system and edit their information
StoreManager can enable Customers created by StoreOfficers to use the system
StoreManager can see the complete list of all Customers with relative information
There are also some other paths, but it's possible for me to develop them as these presented cases are done.
Any help/tutorial please?
Thanks,
FZ
After trying some different things, I created the following satisfying schema, which I post here for others so that they can use something solid:
Class User<ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :userable, polymorphic: true
end
Then all the other roles classes similar to the following one:
class Customer < ApplicationRecord
belongs_to :technician
belongs_to :store_officer
has_one :user, as: :userable, dependent: :destroy
has_one :address, as: :addressable, dependent: :destroy
accepts_nested_attributes_for :user, :address
end
Accordingly, I created all the needed fields using migrations in the database.
Then I put in every controller the code before_action :authenticate_user!.
After populating the db a bit, I can now login with different users inserted using rake db:seed.
This is my routes.rb file:
Rails.application.routes.draw do
devise_for :users
resources :store_managers
resources :store_officers
resources :items
resources :technicians
resources :customers
resources :addresses
resources :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
What do you all think about this setup?
Now I want to introduce CanCanCan to my project. Please validate the following steps I'm going to do:
Run rails g cancan:ability
Put all the rules in the ability.rb file:
if user.admin?
can :manage, :all
elsif user.store_manager?
can :read, Customer
can :create, Customer
can :update, Item do |item|
item.try(:user) == user
end
can :destroy, Item do |item|
item.try(:user) == user
end
elsif user.store_officer?
can :read, Customer
end
.
.
.
Create the methods in user.rb model to check roles:
def customer?
self.userable_type == Customer
end
Put load_and_authorize_resource in every controller
Do you think this approach is the correct one? Or maybe I should put methods/definitions in other files?
Thanks,
FZ
I'm using Rails 4 and I'm trying to add first name and last name fields to the sign up process. I'm using Devise to handle authentication.
I've added first_name and last_name columns to my user model through a migration. I also added the following to my application_controller.rb file:
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :email, :password, :password_confirmation, :remember_me) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email, :password, :remember_me) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password) }
end
However when I sign up, the first_name and last_name field can be left blank and even when they are populated the values are not saved to the user object.
How can I:
Force those fields to be required on sign up? I tried adding 'validates_presence_of :first_name, :last_name, :email' to the user model but had to remove it since the form for some reason always thinks the first_name and last_name fields are blank.
Update devise create action so that it saves the values passed in through the devise/registrations/new.html.erb file?
I have a Person model that i want to associate with this user (associations are created successfully and i have forms that edit both person and user fields but not sure how to build that into the devise sign up process.
Any help would be appreciated.
This is covered in the devise wiki
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-with-something-other-than-their-email-address
I am attempting to create a rails 3.2.13 app where when the user is created a password is auto generated for that user. Right now I am using a before_validate to generate and assign the password to the password and password_confirmation fields on the user object before it is creates but devise still complains that the password is still blank.
What is the best approach to get devise to accept the password that I have generated for my user object? It would be nice to be able to do this without having to overwriting the internal validation if possible.
I don't known what you are doing wrong... Tried quickly here and everything turned out ok.
Here is my model
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
before_validation :set_user_password
def set_user_password
#password = Devise.friendly_token
end
end
I didn't even had to set password_confirmation just password and it saved without errors at the rails console.
The previous solution is awesome. But you can not reset your password. set_user_password should only execute when creating account.
before_validation :set_user_password, :on => :create
def set_user_password
#password = Devise.friendly_token
end
I'm using Devise for authentication with two custom fields added = :organization_id and :username. I also generated a scaffold for the Organization which simply consists of Name.
Currently when users sign up they can type in an Organization ID (integer) and a username (string).
Users belong_to organizations, and organizations has_many users.
Here's what my models look like (I left everything else untouched except for the files inside app/views/devise/registrations to add organization_id and username):
#user.rb
class User < ActiveRecord::Base
belongs_to :organization
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :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, :organization_id, :username
end
#organization.rb
class Organization < ActiveRecord::Base
has_many :users
end
What I would like is for an organization to be automatically created when a user signs up without the user having to specify the organization_id.
Also, ideally the #organization.name would be exactly the same as :username
How would I go about doing this?
I've seen the Railscast on nested model forms but he's creating a question inside the survey form, and questions belong to a survey. I need to do it the other way around (create an organization inside the user form, where users belong to a survey.)
Any help and suggestions would be greatly appreciated..
class User < ActiveRecord::Base
before_create :create_organization
private
def create_organization
self.organization = Organization.create :name => self.username
end
end
The create_organization method will be executed right before the sql query which creates the user. It'll create a new organization and assign it to the user.
I'm new to rails (rails 3) and I am learning in practice.
I want to create a User-profile relation. I have created a User model with devise, and that is working well. Then I created a Profile model. The idea is to register an user and the show information about his profile and if the user wants, complete the profile.
But, the profile is related with posts. So, I need to create an empty profile with the register action of the user.
How can I do that?
My idea is to change the UsersController#create method to build the empty profile, but i don't know how.
My models
class User
include Mongoid::Document
devise :database_authenticatable, :registerable, :token_authenticable,
:omniauthable,
:recoverable, :rememberable, :trackable, :validatable
field :username
key :username
embeds_one :profile
attr_accessible :username,:password,:password_confirmation,:remember_me
class Profile
include Mongoid::Document
field :name
field :lastname
...
...
embedded_in :user, :inverse_of => :profiles
referenced_many :posts
Some idea?
It looks like you're only embedding one profile (embeds_one :profile). It should be user.profile, not user.profiles. Also, user.profile will return an instance of that document, not an array of many documents.
You could do something like this in your controller.
user.profile.create(... put any params here ...)
In your view you would then display
<h2>Welcome <%=#user.profile.username %></h2>
You also need to change
embedded_in :user, :inverse_of => :profiles
to
embedded_in :user, :inverse_of => :profile
To see if the user has a profile or not, just see if user.profile returns nil.