Reputation: 872
I asked this kind of question yesterday, but after I worked on the problem couple of hours, I learned that, the question I asked yesterday wan't the problem I was having. So, I decided to ask again.
User Model:
EMAIL_REGEX = /\A^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$\z/
# Matches -> [email protected] [email protected] [email protected]
# Non-Matches -> hello@worl_d.com he&[email protected] .hello@wor#.co.uk
# http://regexlib.com/REDetails.aspx?regexp_id=333
ALL_LETTERS_AND_SINGLE_SPACES = /\A^([a-zA-Z]+\s?)*$\z/
ALL_LETTERS_AND_NUMBERS = /\A^[a-zA-Z0-9]+$\z/
WEBSITE = /\A(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?\z/
# First Name
validates :first_name,
presence: {message: 'First name cannot be blank'},
length: {maximum: 50, message: 'First name cannot be longer than 50 characters'},
format: {with: ALL_LETTERS_AND_SINGLE_SPACES, message: 'First name should contain only letters and single space'}
# Last Name
validates :last_name,
presence: {message: 'Last name cannot be blank'},
length: {maximum: 50, message: 'Last name cannot be longer than 50 characters'},
format: {with: ALL_LETTERS_AND_SINGLE_SPACES, message: 'Last name should contain only letters and single space'}
# Email
validates :email,
presence: {message: 'Email cannot be blank'},
length: {maximum: 100, message: 'Email cannot be longer than 100 characters'},
format: {with: EMAIL_REGEX, message: 'Email is not valid'},
uniqueness: {case_sensitive: false, message: 'This email is already registered'},
confirmation: {message: 'Email address does not match'}
# Password
validates :password_digest,
presence: {message: 'Password cannot be blank'},
length: {minimum: 8, message: 'Password length should be minimum 8 characters'}
# Username
validates :username,
presence: {message: 'Username cannot be blank'},
length: {minimum: 3, message: 'Email cannot be shorter than 3 characters'},
format: {with: ALL_LETTERS_AND_NUMBERS, message: 'Username should contain only letters and numbers'},
uniqueness: {case_sensitive: false, message: 'This username is already in use'}
# Website
validates :website,
format: {with: WEBSITE, message: 'Invalid email format. Make sure you don\'t have http:// in your link'}
# Information
validates :information,
length: {maximum: 100, message: 'Information cannot be longer than 99 characters'}
As you can see, I have validation for some of the columns in my database. What I need is to validate first_name, last_name, email, and password when user is signing up, and validate first_name, last_name, and also website, information, username when user editing his/her profile settings.
But rails is automatically validating all the columns either you have username field in your signup page or not. It just validates everything. But I don't want rails to validate username, or website when signing up.
Profile Controller:
def update
# Find an existing object using form parameters
@profile = User.find_by_id(current_user.id)
# Update the object
if @profile.update_attributes!(settings_profile_params)
# If save succeeds, redirect to itself
redirect_to request.referrer
else
# If save fails, redisplay the form so user can fix the problems
render('edit')
end
end
private # user_params is not an action, that is why it is private.
def settings_profile_params
params.require(:user).permit(:first_name, :last_name, :username, :school, :program, :website, :information)
end
Users Controller:
def create
# Instantiate a new object using form parameters
@user = User.new(user_params)
# Save the object
if @user.save
# If save succeeds, redirect to the dashboard action
cookies[:authorization_token] = @user.authorization_token
redirect_to dashboard_path
else
# If save fails, redisplay the form so user can fix the problems
render('new')
end
end
private # user_params is not an action, that is why it is private.
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :email_confirmation, :password)
end
I thought rails would validate the ones that are passed in strong parameters only but it's not. I believe it supposed to be very easy to solve but I can't.
Thank you.
Upvotes: 2
Views: 438
Reputation: 2381
I don't know of an idiomatic way to to do this. For individual validations you want to only run on update, you can do
validates :username,
...
on: :update # or on: :create
Or if you want them only to run when the attribute has been provided in the form,
validates :username,
...
if: :username_changed?
For a more radical solution, you may want to consider breaking your model up into two--one containing the attributes created on signup (User
), and one with the rest of the attributes (a UserDetails
or UserProfile
) that belongs_to :user
. At that point, having different validation logic at different stages in your workflow becomes simple.
Upvotes: 1
Reputation: 5740
Validations in models are most of the time about forms.
Ryan Bates has issued an excellent RailsCast on how to refactor your model, in a way that you use a different object for each one of your forms.
This way, you can combine models and/or define different behaviours and/or validations, depending on the form that submits the data.
The way to do it is quite long to describe, so posting code here would be messy.
I strongly suggest visiting the above link, you will have your answer there.
Upvotes: 0
Reputation: 10951
You can use :if option:
class Order < ActiveRecord::Base
validates :card_number, presence: true, if: :paid_with_card?
def paid_with_card?
payment_type == "card"
end
end
But I think you're looking for allow_nil or allow_blank option:
3.1 :allow_nil
The :allow_nil option skips the validation when the value being validated is nil.
class Coffee < ActiveRecord::Base
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }, allow_nil: true
end
3.2 :allow_blank
The :allow_blank option is similar to the :allow_nil option. This option will let validation pass if the attribute's value is blank?, like nil or an empty string for example.
class Topic < ActiveRecord::Base
validates :title, length: { is: 5 }, allow_blank: true
end
Topic.create(title: "").valid? # => true
Topic.create(title: nil).valid? # => true
Upvotes: -1