I am having an issue with a sign up form. It was created with SimpleForm, authentication is done with Devise. When submitting the form, if the email or password is blank, it will display the error for this twice. In the user model there are presence validations for the first name, last name, profile name, password, and email. These duplicate errors only appear on the blank email and password fields. Any other blank fields will say so once.
Example:
# Errors Prohibited This User From Being Saved:
Email can't be blank
Email can't be blank
Password can't be blank
Password can't be blank
user.rb:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :profile_name
validates :first_name, :last_name, :email, :profile_name, :password, presence: true
validates :profile_name, uniqueness: true,
format: {
with: /^[a-zA-Z0-9_-]+$/
}
has_many :posts
def full_name
first_name + " " + last_name
end
end
registrations/new.html.erb:
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="formGroupLeft">
<%= f.input :first_name, :input_html => { :class => 'formGroupInput'} %>
</div>
<div class="formGroupRight">
<%= f.input :last_name, :input_html => { :class => 'formGroupInput'} %>
</div>
<div class="formGroupLeft">
<%= f.input :email, :input_html => { :class => 'formGroupInput'} %>
</div>
<div class="formGroupRight">
<%= f.input :profile_name, :input_html => { :class => 'formGroupInput'} %>
</div>
<div class="formGroupLeft">
<%= f.input :password, :input_html => { :class => 'formGroupInput'} %>
</div>
<div class="formGroupRight">
<%= f.input :password_confirmation, :input_html => { :class => 'formGroupInput'} %>
</div>
<div class="formActions">
<%= f.button :submit, "Sign Up" %>
</div>
<% end %>
Why might this be? And how can I attempt to fix it?
Looks like you've specified the devise validatable plugin, which adds email/password validations.
class User
devise :database_authenticatable, ... :validatable
end
Since you're specifying your own validations, I would omit the devise validatable plugin.
Related
I am getting the error:
NoMethodError in RegistrationsController#create
undefined method avatar_content_typefor #
when I try to sign up a new user.
Here is my app/controllers/registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation, :username, :firstname, :lastname, :image, :url)
end
def account_update_params
params.require(:user).permit(:email, :password, :password_confirmation, :current_password, :username, :firstname, :lastname, :image, :url)
end
end
User.rb looks like this:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates_uniqueness_of :username
has_many :articles
has_many :comments
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }
#, default_url: "/images/:style/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
end
app/views/registrations/edit.html.erb:
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :username, required: true, autofocus: false, label: false, placeholder: "Set Your UserName" %>
<%= f.input :email, required: true, autofocus: true, label: "Your Email Goes Here..." %>
<%= f.input :firstname, required: false, autofocus: false %>
<%= f.input :lastname, required: false %>
<%= f.input :image, as: :file %>
<%= image_tag #user.image.url(:thumb), class: "img-circle" %>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<p>Currently waiting confirmation for: <%= resource.unconfirmed_email %></p>
<% end %>
<%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %>
<%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %>
<%= f.input :password_confirmation, required: false %>
</div>
<div class="form-actions">
<%= f.button :submit, "Update" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
<%= link_to "Back", :back %>
I'm getting Email has already been taken error even on login page. Earlier this message was not displayed now I don't know why its checking :uniqueness of email on login.
I have even tried commenting validates_uniqueness_of :email or specify it on login(validates_uniqueness_of :email, :on => :create) but nothing seems to be working.
I'm using devise gem.
Here is my login page:
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name) , :validate=>true) do |f| %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<p>
<%= f.password_field :password %>
</p>
<div id="lower">
<% if devise_mapping.rememberable? -%>
<%= f.check_box :remember_me %> <%= f.label :remember_me ,:class=>"check" %>
<% end %>
<%= f.submit "Login",:value=>"Login" %>
<div>
<%= link_to "Forgot your password?",new_password_path('registered_user') %>
</div>
<div>
<%= link_to "Sign Up", new_registered_user_registration_path %>
</div>
</div>
<% end %>
SessionController
def create
respond_to do |format|
format.html{ super }
format.json do
.................
end
format.js do
.................
end
end
end
My route
devise_for :registered_users, :path_names=> {:sign_up=> "signup",:sign_in=> "login", :sign_out=> "logout"}, :controllers => { :registrations => "registrations",:sessions=>"sessions" }
My model :
devise :database_authenticatable, :registerable,
:recoverable, :trackable, :validatable
validates_presence_of :email,:phone, :address1,:first_name, :last_name,:city , :state, :zip_code
validates :email, :email_format => true
validates_presence_of :password, :on => :create
validates_presence_of :current_password, :on => :edit
validates_length_of :password, :minimum => 6, :on => :create
I have found a quick and dirty way :) add inline validation in this way :
<%= f.email_field :email , :validate => { :uniqueness => false },:type=>"text" %>
Please let me know when you guys get what is the issue.
I have searched for quite a long, but could not found the solution. Here are my models:
web.rb
class Web < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :user_type, :remember_me
belongs_to :role, :polymorphic => true
end
user.rb
class User < ActiveRecord::Base
has_one :web, :as => :role
attr_accessible :dob, :fname, :lname
end
org.rb
class Org < ActiveRecord::Base
has_one :web, :as => :role
attr_accessible :name, :website
end
Everything seems fine until i use the simple_form_for instead of normal form_for in the devise/registration/new.html.erb
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => 'form-horizontal' }) do |f| %>
<%= f.input :email, label: false, :input_html => { :class => "span6", placeholder: "Email", type: "email", required: true}%>
<%= f.input :password, label: false, :input_html => { :class => "span6", placeholder: "Password", type: "password" }%>
<%= f.input :password_confirmation, label: false, :input_html => { :class => "span6", placeholder: "Re-enter Password", type: "password" }%>
<%= f.input :user_type, as: :hidden, :input_html => { :value => user_type} %>
<%= f.simple_fields_for resource.role do |rf| %>
<%= render :partial => "#{child_class_name.underscore}_fields", :locals => { :f => rf } %>
<% end %>
<%= f.submit "Sign up" %>
<% end %>
The nesting part puts the partial with appropriate model_fields name which contains corresponding fields.
*_org_fields.html.erb*
<%= f.text_field :name, :class=>"span6", :type=>"text", :placeholder=>"Name", :required=>"" %><br />
<%= f.text_field :website, :class=>"span6", :type=>"text", :placeholder=>"Website", :required=>"" %>
The problem is with the f.simple_fields_for, if i remove simple_ everything works fine. But i don't want it to be removed. The error i encounter is:
ActiveModel::MassAssignmentSecurity::Error in Devise::RegistrationsController#create
Can't mass-assign protected attributes: org
The request parameters are:
{"utf8"=>"✓",
"authenticity_token"=>"NnsyNdrrKJmd8QutqVs6HqZi0EnQmAmZF7zGYqnu+rI=",
"web"=>{"email"=>"",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"user_type"=>"org",
"org"=>{"name"=>"",
"website"=>""}},
"commit"=>"Sign up"}
Please Help.
In Web, add:
attr_accessible :role_attributes
accepts_nested_attributes_for :role
Edit: Originally had it as User but Devise resource is Web.
Edit2: Missed the as: :role. Changed the attr values to reflect.
I am using the Devise gem to authenticate users. I have a User model and an Address model relation where each User has_one :address and each address belongs_to :user. When I try to register a new user I get the following error on page load: unknown attribute: user_id. The trace points to the line <% resource.build_address... seen in my view.
If I just delete that line from my view the page will load but none of my nested form fields show up.
In Rails console I can create and save an address then use that saved address as an attribute for a new User that will save.
The view is as follows:
<% resource.build_address unless resource.address %>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= f.email_field :email, :autofocus => true, placeholder: "Your email", class: 'input-block-level' %><br>
<%= f.password_field :password, placeholder: "Password", class: 'input-block-level' %><br>
<%= f.password_field :password_confirmation, placeholder: "Confirm password", class: 'input-block-level' %><br>
<%= f.text_field :favorite_cuisine, placeholder: "Favorite cuisine", class: 'input-block-level' %><br>
<%= f.fields_for :address do |address_form| %>
<%= address_form.text_field :street_one, placeholder: "Street", class: 'input-block-level' %><br>
<%= address_form.text_field :street_two, placeholder: "Street #2", class: 'input-block-level' %><br>
<%= address_form.text_field :city, placeholder: "City", class: 'input-block-level' %><br>
<%= address_form.text_field :state, placeholder: "State", class: 'input-block-level' %><br>
<%= address_form.text_field :zip, placeholder: "zip", class: 'input-block-level' %><br>
<% end %>
<% end %>
My User model:
has_one :address, :dependent => :destroy
accepts_nested_attributes_for :address
# 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,
:favorite_cuisine, :username, :address
validates_presence_of :email
validates_presence_of :address
My Address model:
belongs_to :user
attr_accessible :city, :state, :street_one, :street_two, :zip, :user_id
validates_presence_of :city
validates_presence_of :state
validates_presence_of :street_one
validates_presence_of :zip
Where am I going wrong here?
rails g migration AddUserIdToAddresses
Then edit the file, and
def change
add_column :addresses, :user_id, :integer
end
then rake db:migrate
Try something like this:
<%= f.fields_for (resource.address || :address), ... %>
Because the form is nested, it should build a new one with form submission to my knowledge.
Even though I added accepts_nested_attributes_for to my model.
it still says "Can't mass-assign protected attributes"
What else am I supposed to do in order to avoid this???
models/user.rb
class User < ActiveRecord::Base
validates_presence_of :username
validates_uniqueness_of :username
validates_length_of :username, :within => 4..10
acts_as_messageable
has_one :user_profile
accepts_nested_attributes_for :user_profile
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :user_profile_attributes
def mailboxer_email(message)
email
end
# def name
# email
# end
end
models/user_profile.rb
class UserProfile < ActiveRecord::Base
belongs_to :user
accepts_nested_attributes_for :user
attr_accessible :nickname
end
views/registration/edit.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :nickname %><br />
<%= f.fields_for :nickname_attributes, #user.user_profile do |user_profile| %>
<%= user_profile.text_field :nickname %>
<% end %>
</div>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<%= recaptcha_tags :display => {:theme => 'red'} %>
<div><%= f.submit "Update" %></div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
<%= link_to "Back", :back %>
attr_accessible defines the attributes you want the user to be able to mass assign. Just make sure it has all the attributes you want in there.
To be fair, you can remove attr_accessible if you don't care about it and the error will disappear (but all your model fields will be mass assignable).
in edit.html.erb
wrong:
f.fields_for :nickname_attributes,
correct:
f.fields_for :user_profile_attributes,