Can't seem able to show validation errors on rails - ruby-on-rails

I've been reading rails and ruby tutorials and just got started with my first project. Everything is going well but I'm having a problem showing validation errors for new users. This is my controller code:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to ''
else
redirect_to '/signup'
end
end
private
def user_params
params.require(:user).permit(:name, :lastname, :nickname, :email, :password)
end
end
And this is my form. I'm omitting all inputs but the nickname one, because I'm testing the validation with it.
<%= form_for(#user) do |f| %>
<div class='form-group'>
<%= f.text_field :nickname, :placeholder => "User name", :class => "form-control", :required => true, :minlength => "2", :maxlength => "24" %>
<div class="text-danger">
<%= #user.errors[:nickname][0] %>
</div>
</div>
<% end %>
I just show the first related error to see if it's working, and avoid any Ifs that would make me doubt if it works or not. The validation on the class is:
class User < ApplicationRecord
has_many :books
has_secure_password
validates :nickname, uniqueness: true
end
When I create a new user by console and try to save it with the same nickname as another it wont save, so the validation works fine. But no error is shown in the view, it just goes back to the signup form and that's all. I'm using ruby 2.2.6 and rails 5.0.1. If I'm missing anything let me know.

Instead of redirect render new action template:
def create
#user = User.new(user_params)
if #user.save
redirect_to ''
else
render 'new'
end
end
When you do redirect you loose #user object that contains validation errors. That is why they are not visible in view

Related

rails validations error messages not working

I am trying to make a login in and sign up page but when i try to validate the email and password no error messages pop up I though they are supposed to pop up the the condition isn't met.
i have tried error messages through layouts view and helper but none work or are too confusing for me to understand.
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.create(password: params[:password], email: params[:email], firstname: params[:firstname], lastname: params[:lastname])
if #user.save
redirect_to user_path(#user)
else
redirect_to root_path
end
end
def show
#user = User.find(params[:id])
end
end
This is my users controller
This is my user model
class User < ApplicationRecord
has_secure_password
validates :email, presence: true, uniqueness: true
validates :password, length: { minimum: 4 }
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+
[a-z]{2,})\Z/i, :message => "hollksd"(just for testing)
end
This is my new user view
<%= form_for #user do |form| %>
<p> First name:<%= form.text_field :firstname %></p>
<p>Last name:<%= form.text_field :lastname %></p>
<p>Email:<%= form.email_field :email %></p>
<p>Create password:<%= form.password_field :password %></p>
<%= form.submit %>
<%end%>
if anyone could help it would be appreciated!
It seems like your html elements are not associated to User model please try to use form_for tag instead somewhat like below
<%= form_for #user do |form| %>
<%= form.text_field :first_name %>
<%= form.text_field :last_name %>
<%= form.submit %>
<%end%>
Also please use render :new instead of redirect_to root_path
You you need to update your create action to something like this:
def create
#user = User.new(password: params[:password], email: params[:email], firstname: params[:firstname], lastname: params[:lastname])
if #user.save
redirect_to user_path(#user)
else
render :new
end
end
Why render new when it fail to save? Because we need to let know know that this form is not valid, and by rendering new with the #user object, you get access to #user.errors where you can do whatever you like (formally form will render a red border and error message next to input).

Getting my Ruby on Rails page to save the user's email without using devise

I am building a one page website where visitors will simply be able to submit their email address. The only goal in the database is to get an email (no name, etc). There is only one page visible at first, which is the homepage. If the user submits an email already in use, it sends the user to an error page. If the email is not in use, it sends the user to a success page.
I have asked a question about this previously, and after a lot of comments and trial and error, it appeared that it worked and then it stopped working. When I do Rails C, there is only one user in the system and that user doesnt have an email...
Here is what my user migration looks like :
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :email
t.timestamps
end
add_index :users, :email, unique: true
end
end
Here is what my user model looks like:
class User < ApplicationRecord
end
Here is what users/new.html.erb looks like:
<%= form_for #user, as: :post, url: users_path do |f| %>
<div class="wrapper">
<%= f.email_field :email , id: "search", class:"search input" %> <br />
<%= f.submit "yep", class: "submit input" %>
</div>
<% end %>
Here is my user controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:email])
if #user.save
redirect_to '/users/success'
else
redirect_to '/users/error'
end
end
def show
end
end
Here are my routes:
Rails.application.routes.draw do
root "users#new"
resources :users
end
When i run the code, it renders the homepage but when i click on submit, it sends me on a page called show.html.erb with http://localhost:3000/users/error on my brownser. No users are being saved in the console.
EDIT:
My model is
class User < ApplicationRecord
validates_uniqueness_of :email
end
It is still not working....
change new.html.erb as
<%= form_with(model: #user, local: true) do |f| %>
<div class="wrapper">
<%= f.email_field :email , id: "search", class:"search input" %> <br />
<%= f.submit "yep", class: "submit input" %>
</div>
your controller will be
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to user_path(#user), notice: "yeh!!!!"
else
redirect_to new_user_path, notice: "email already registered"
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:email)
end
end
add
<p id="notice"><%= notice %></p> to your application.html.erb in layouts
rest as your question
There are a couple things wrong here.
You're so close, but you're misusing the as: attribute of form_for. Perhaps you think that will send as a POST request, but instead that is actually wrapping your form params in an object called "post". I saw this in the comments on another thread.
Remove the as: attribute and the helper will again wrap your params in the user object. While we're at it, you should also be able to remove the url: attribute as well since Rails form helpers are smart enough to infer that this is a new resourceful record and output the create URL as well as the POST action accordingly.
You need your controller to expect a whole "user" object instead of just checking for the email param. ALSO, assuming you're on Rails 4 or higher, you need to permit the email attribute to be mass-assigned on your User object. See the code.
def create
#user = User.new(params.require(:user).permit(:email)) # Not params[:email]
if #user.save
redirect_to '/users/success'
else
redirect_to '/users/error'
end
end
Also be careful about duplicate emails with different cases. The default in Rails is case-sensitive validation which means "JIM#gmail.com" would not trigger a validation error against "jim#gmail.com". You can fix this with.
class User < ApplicationRecord
validates :email, uniqueness: { case_sensitive: false }
end
BONUS!
Nowadays, it's better to move over to form_with (instead of form_for). It's on its way to becoming the new Rails standard and also makes a few of these things easier. The one point you'll want to keep in mind is that with form_with (and general Rails assumptions), forms are remote by default. So if you want to trigger a full page submit/refresh, add local: true to your form_with helper.
<%= form_with model: #user, local: true do |f| %>
<div class="wrapper">
<%= f.email_field :email , id: "search", class:"search input" %> <br />
<%= f.submit "yep", class: "submit input" %>
</div>
<% end %>
As you are using resources in routes so def show is called when route is /users/:id. That's why its calling show.html.erb file.
When you try to validate an email, then in model write the validation for it
class User < ApplicationRecord
validates_uniqueness_of :email
end
Hope this helps.
Try to add validates_uniqueness_of in your model
class User < ApplicationRecord::Base
attr_accessor :email
validates_uniqueness_of :email
end
And
def show
#user = User.find(email: params[:email])
end
And if you wanna check all
def show
#user = User.all
end
Please try this.
I hope that helpful

Nested model in Rails3

I have two models user and profile.
I want to save the username and password in user and other user profile details in profile.
Now,
The user model has:
has_one :profile
accepts_nested_attributes_for :profile
attr_accessible :email, :password
The profile model has
belongs_to :user
attr_accessible :bio, :birthday, :color
The user controller has
def new
#user = User.new
#profile = #user.build_profile
end
def create
#user = User.new(params[:user])
#profile = #user.create_profile(params[:profile])
if #user.save
redirect_to root_url, :notice => "user created successfully!"
else
render "new"
end
end
The view new.html.erb have fields for both user and profile.
However,when I run this web application it shows error:
Can't mass-assign protected attributes: profile
on debug it stuck at #user = User.new(params[:user]) in create action
so,what is wrong? I have also tried putting :profile_attributes in attr_accessible but it doesn't help!please help me to find out solution.
First off, as suggested by #nash, you should remove #profile = #user.create_profile(params[:profile]) from your create action. accepts_nested_attributes_for will automatically create your profile for you.
Check that your view is set up correctly for nested attributes. Should shouldn't be seeing anything in params[:profile]. The profile attributes need to come through in params[:user][:profile_attributes] for nested models to work correctly.
In summary, your create action should look like this:
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url, :notice => "user created successfully!"
else
render "new"
end
end
Your form view (typically _form.html.erb) should look something like this:
<%= form_for #user do |f| %>
Email: <%= f.text_field :email %>
Password: <%= f.password_field :password %>
<%= f.fields_for :profile do |profile_fields| %>
Bio: <%= profile_fields.text_field :bio %>
Birthday: <%= profile_fields.date_select :birthday %>
Color: <%= profile_fields.text_field :color %>
<% end %>
<%= f.submit "Save" %>
<% end %>
For more information, see this old but great tutorial by Ryan Daigle.

Why isn't my rails controller/form persisting any data to my local database?

I'm new to Ruby on Rails, and as my first project I'm creating a beta sign-up page for my startup. I just want to save the users email address to a database for future use, and I am not able to persist any data into my database. I can add emails through the rails console, but my form/controller are not working. What's wrong?
User Model:
class User < ActiveRecord::Base
attr_accessible :email
before_save { |user| user.email = email.downcase }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness:
{case_sensitive: false }
end
User Controller:
class UsersController < ApplicationController
def index
end
def create
User.create params[:email]
redirect_to :back, :notice => "Success!"
end
end
Home page HTML:
<h1>######</h1>
<p>Welcome to #####! Give us your email address, and we'll keep you informed on our
latest happenings.
You'll also be placed on the list for our private alpha and beta testings.</p>
<%= render 'form' %>
Form Partial:
<%= form_for User.new do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.submit %>
<% end %>
Thanks!
First, create the user with params[:user] not params[:email]. If you want just the email address, put params[:user][:email].
This is because params is a nested hash and looks like this:
params[:user] = { email: "name#example.com" }.
Second, use conditional logic in case the email address does not pass validation and doesn't save.
#user = User.new(params[:user])
if #user.save
redirect_to :back, :notice => "Success!"
else
# display error messages
end
or if you want to get verbose:
#user = User.new(:email => params[:user][:email])
This is wrong:
User.create params[:email]
It should be:
User.create params[:user]

Why is my rails simple validation not working

I have a very basic rails app. I am playing around with validation.
Controller
class PagesController < ApplicationController
def new
#user = User.new
end
def edit
#user = User.new(:state => params[:state], :country => params[:country])
#user.save
end
end
Model
class User < ActiveRecord::Base
validates_presence_of :country
validates_presence_of :state
end
Views/pages/edit.html.erb
<% form_for :user, #user, :url => { :action => "edit" } do |f| %>
<%= f.text_field :country %>
<%= f.text_field :state %>
<%= submit_tag 'Create' %>
<% end %>
All I want to do is click Create when I have not entered anything and then have a validation come up and list the required fields. I've read some tutorials and they make it so simple. Why can't I get this to work? what am i doing wrong? When i create a scaffold then it works ok but that generates a scaffold.css in public/stylesheets. W/out scaffold right now i have no stylesheet in the public folder.
you're sending the form to the "edit" action, which doesn't do any processing. You need it to go to the "create" action, which should look something like this:
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = 'Your user was successfully created.'
redirect_to users_path
else
render :action => 'edit'
end
end
Your form_for line can be short and sweet. Also, you need to call error_messages to get the auto-generated list of errors:
<% form_for #user do |f| %>
<%= f.error_messages %>
...other fields go here...
<% end %>
See Rails conditional validation: if: doesn't working
It seems like you think validates ... if: works differently as it actually does. This line
validates :to_id, presence: true, if: :from_different_to?
translates to validate that the to_id is present if the from_different_to method returns true. When from_different_to evaluates to false then do not validate.

Resources