I'm using Rails 3.2.2 and am not getting the field_with_errors div when the validation fails.
views/sessions/new.html.erb
<%= form_tag sessions_path do %>
<p><%= label_tag :email %><br />
<%= email_field_tag :email %></p>
<p><%= label_tag :password %><br />
<%= password_field_tag :password %></p>
<p><%= submit_tag "Log in" %></p>
<% end %>
controllers/sessions_controller.rb
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password]) && user.account.subdomain == request.subdomain
session[:user_id] = user.id
redirect_to home_path
flash[:notice] = "Logged in!"
else
flash.now[:error] = "Invalid email or password"
render 'new'
end
end
models/user.rb
attr_accessible :first_name, :last_name, :email, :password, :password_confirmation
has_secure_password
validates :email, :presence => true, :uniqueness => true
validates :password, :presence => true, :on => :create
I'm getting the flash message, but my view doesn't render the field_with_errors wrapper divs if the validation fails. Any ideas?
Thanks.
It's no longer included by default, you need to render your own error messages.
Here's some sample code generated in a scaffold for a Post model:
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
You can then extract that into a partial for re-use with your other models.
I think the field_with_errors functionality only works with form_for. If you want it, you could change your authenticate method to add errors to the the #user object (it will have to be an instance variable for this to work), and then change your form to:
<%= form_for(#user) do |f| %>
<%= f.error_messages %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<p><%= f.label :password %><br />
<%= f.password_field :password %></p>
<p><%= f.submit "Log in" %></p>
<% end %>
Related
In my users views new.html.erb
<% provide(:title, 'SignUp') %>
<%= form_with(model: #user, local: true) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<br>
<%= f.label :email, "Email" %>
<%= f.email_field :email %>
<br>
<%= f.label :password, "Password" %>
<%= f.password_field :password %>
<br>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
<br>
<%= f.submit "Create Account", class: "btn btn-outline-success" %>
<% end %>
In my user controller users_controller.rb looks like:-
class UsersController < ApplicationController
def new
#user = User.new
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
if #user.invalid?
puts "Hi"
flash[:success] = "Invalid Data"
render 'new'
else
flash[:success] = "Welcome to sample app"
#user.save
redirect_to #user
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
This is my errors file /views/shared/_errors.html.erb
<% if #user.errors.any? %>
<div class="alert alert-danger">
The form contains <%= pluralize(#user.errors.count, "error") %>
</div>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li> <%= msg %> </li>
<% end %>
</ul>
<% end %>
render 'new' is not working in create action. I include the errors.html.erb file in new file so it can display the error, but it is not working.
Try form_for instead of form_with.
<%= form_for(#user) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<br>
<%= f.label :email, "Email" %>
<%= f.email_field :email %>
<br>
<%= f.label :password, "Password" %>
<%= f.password_field :password %>
<br>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
<br>
<%= f.submit "Create Account", class: "btn btn-outline-success" %>
<% end %>
So I'm using form_with, and my code is placed in views/users/new.html.erb
<% content_for :title, "Sign Up" %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#user.errors.count, "error") %>
prohibited this user from being saved:
</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_with model: #user do |f| %>
<%= f.label :email %>
<%= f.email_field :email, :placeholder => 'E-mail address' %><br>
<%= f.label :password %>
<%= f.password_field :password, :placeholder => 'Password' %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, :placeholder => 'Password confirmation' %><br>
<label>Are you a cleaner or customer?</label>
<%= f.select :user, User::SUB_CLASSES, include_blank: true %><br>
<%= f.submit "Next" %>
<% end %>
My controller has the following code
def new
#user = User.new
render :layout => "beforelogin"
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
if #user.sub_class == "Cleaner"
redirect_to new_cleaner_path
else
redirect_to new_customer_path
end
else
render :new
flash[:alert] = "Your registration could not be completed"
end
end
Now when I fill out the form on the user/new.html.erb route, nothing happens. The button just clicks. No errors pop up. I even tried to add to the top of the form, <%= form_with model: #user, url: users_path, method: "post" do |f| %>. Still the same response.
By default form_with attaches the data-remote attribute to the form. As a consequence, the form will be submitted using Ajax.
In case you want to disable this feature, you need to set the option local to true.
like this:
<%= form_with model: #user, local: true do |f| %>
Every time I try to sign up on my rails form, it says password can not be left blank, and I am putting in a password every time. I've been staring at my code for hours now trying to figure it out, and I can't.
Here is my users/new.html.erb
<h1>Sign Up</h1>
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
<div class="error_messages">
<h2>Form is invalid</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="actions"><%= f.submit "Sign Up" %></div>
<% end %>
Users controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to root_url, notice: "Thank you for signing up!"
else
render "new"
end
end
private
def user_params
params.required(:user).permit(:name, :email, :password_digest)
end
end
User model:
class User < ActiveRecord::Base
has_secure_password
validates_uniqueness_of :email
end
Thanks for your help, I really am coming here as a last resort.
Change your user_params method to:
def user_params
params.required(:user).permit(:name, :email, :password)
end
Since you are dealing with password field/method I think you should allow it.
Add password to your parms.require method
i.e.
def user_params
params.required(:user).permit(:name, :email, :password)
end
I'm new to rails and trying to implement a user registration page (Create in CRUD). In addition to a submit button, I also want a cancel button so that user can click it and go back to index page. I have done the following but the cancel button still registers the user.
Haml code (new.html.haml):
=form_tag users_path, :method => :post do
%p= label :user, :username, "User Name"
%p= text_field :user, :username
... (other information)
= button_tag "Submit", :type => 'submit'
= button_tag "Cancel", :type => 'cancel'
Rails code(users_controller.rb):
class UsersController < ApplicationController
before_filter :check_for_cancel, :only => [:create, :update]
def create
vals = params[:user]
if(User.exists(vals[:username]))
flash[:warning] = "#{vals[:username]} already exists! Please try a new one. "
else
vals[:create_date] = DateTime.current
vals.except!(:confirm_password)
#user = User.create(vals, :without_protection => :true)
unless #user==nil
flash[:notice] = "#{vals[:username]} has been registered. "
else
flash[:warning] = "#{vals[:username]} has not been registered successfully. "
end
end
redirect_to users_path
end
...(other CRUD methods)
def check_for_cancel
if(params[:commit]=="cancel")
flash[:notice] = "Registration is cancelled. "
redirect_to users_path
end
end
end
Thanks.
I don't quite understand how it works but after some experimentation the following code works.
In haml,
= button_tag "Submit", :type => 'submit', :name => 'submit'
= button_tag "Cancel", :type => 'cancel', :name => 'cancel'
In rails,
def check_for_cancel
if(params.key?("cancel"))
flash[:notice] = "Registration is cancelled. "
redirect_to users_path
end
end
Basically, when I give button a name, the params will have a entry params["cancel"]="" or params["submit"]="", depending on the key being clicked.
The only button types that are legal are submit, reset, and button (http://developer.mozilla.org/en-US/docs/Web/HTML/Element/button). cancel is not a valid value for the type attribute.
You'll have to create a workaround to pass the "cancel" message across the button submit. See previous answer for options:
How to create a HTML Cancel button that redirects to a URL
You could use link_to and style it as a button with css and then you don't have to have any check in your controllers.
= link_to 'Cancel', users_path, class: 'btn'
If you are on a development team that has a dedicated designer who creates the front-end markup then to work seamlessly and easily, I'll advice you use html and erb instead of haml for rendering your views.
A simple form to achieve what you want using html and erb is
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_name %><br />
<%= f.text_field :user_name %>
</div>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.number_field :phone %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
but if you still insist on using haml cause of its brevity then
= form_for(#user) do |f|
- if #user.errors.any?
#error_explanation
%h2
= pluralize(#user.errors.count, "error")
prohibited this user from being saved:
%ul
- #user.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :user_name
%br/
= f.text_field :user_name
.field
= f.label :first_name
%br/
= f.text_field :first_name
.field
= f.label :last_name
%br/
= f.text_field :last_name
.field
= f.label :phone
%br/
= f.number_field :phone
.actions
= f.submit
\#{link_to 'Back', users_path}
As shown above the "link_to" helper method would navigate to the specified path in this case
users_path. Find more info about the link_to helper method http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
<%= button_tag "Cancel", type: :reset %> This work for me
for more ref:- http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
I'm using devise+omniaouth for authenticanton. My users also have a profile, with the following relationship;
class User < ActiveRecord::Base
has_many :authentications
has_one :profile
accepts_nested_attributes_for :profile
attr_accessible :email, :password, :password_confirmation, :remember_me, :profile_attributes
etc.
So my registrations/new.html.erb looks like this:
<% resource.build_profile %>
<%= form_for(resource, :as => resource_name,
:url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :profile do |profile_form| %>
<h2><%= profile_form.label :name %></h2>
<p><%= profile_form.text_field :name %></p>
<% end %>
<h2><%= f.label :email %></h2>
<p><%= f.text_field :email %></p>
<h2><%= f.label :password %></h2>
<p><%= f.password_field :password %></p>
<h2><%= f.label :password_confirmation %></h2>
<p><%= f.password_field :password_confirmation %></p>
<p><%= f.submit "Sign up" %></p>
<br/>
<%= render :partial => "devise/shared/links" %>
<% end %>
<%= render "links" %>
As you can see, the only attribute that I'm trying to fill from the profile is 'name'. This works correctly and when you try to sign up from /users/sign_up, you have to fill name, email and password.
Now, I'm trying to display this registration window from a modal window, so I created:
/views/devise/menu/_registration_items.html.erb with the same info:
<%= form_for(resource, :as => resource_name,
:url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :profile do |profile_form| %>
<h2><%= profile_form.label :name %></h2>
<p><%= profile_form.text_field :name %></p>
<% end %>
<h2><%= f.label :email %></h2>
<p><%= f.text_field :email %></p>
<h2><%= f.label :password %></h2>
<p><%= f.password_field :password %></p>
<h2><%= f.label :password_confirmation %></h2>
<p><%= f.password_field :password_confirmation %></p>
<p><%= f.submit "Sign up" %></p>
<br/>
<% end %>
I also added this to the application controller (it works the same way if I put it in the helper):
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
As explained at https://github.com/plataformatec/devise/wiki/How-To%3a-Display-a-custom-sign_in-form-anywhere-in-your-app
Everything works fine except that the name field doesn't dislpay in the form.(For example, the login form that doesn't have that field name works correctly). I guess that I have to map something else, but I don't know what it is.
Thanks!
I forgot to add the
<% resource.build_profile %>
line at the top of the form.