I have the following validation:
class User < ActiveRecord::Base
...
validates :email, uniqueness: { message: "Email already associated with an account" }
...
end
My class User as a boolean attribute called active, and I would like to incorporate it into the validation logic using conditional. What is the best way to throw a custom validation error message if the conditional user.active? == false?
I would try adding the following two validations:
validates :email, uniqueness: { message: "message 1", if: 'active?' }
validates :email, uniqueness: { message: "message 2", if: '!active?' }
Validations can be represented as instance methods. For example, I have a Student model with first_name and last_name attributes. I want to introduce a validation, which will throw custom errors when either one, or both of the names are empty. I can do this by:
calling the custom method in validate:
class Student < ActiveRecord::Base
...
validate :full_name_validation, on: :create
...
end
and adding my full_name_validation method:
def full_name_validation
if first_name.blank? && last_name.blank?
errors.add(:full_name, 'Full name is required')
elsif first_name.blank?
errors.add(:full_name, 'First name is required')
else
errors.add(:full_name, 'Last name is required')
end
end
Related
I try to add a validation from a blog category only limited at 1 word.
But I try this length: { maximum: 1 }
I doesn't work. Is there a validation to validaes only one word and not uniqueness?
Thank you for your answers
You can make a custom validation:
validates :category, uniqueness: true
validate :category_in_1_word
private
def category_in_1_word
if category.to_s.squish.split.size != 1
errors.add(:category, 'must be 1 word')
end
end
you can try:
validates :category, :format => { :with => /^[A-Za-z]+$/, :message => "Must be single word" }
No Rails doesn't have the validation you need, but you can easily create a custom one:
Try something like this:
class Post < ActiveRecord::Base
validate do
if ... # any custom logic goes here
errors.add :title, "is wrong"
end
end
end
This is my user class:
class User < ActiveRecord::Base
has_secure_password
before_save :valid_email?
validates :username, presence: true,
uniqueness: true
validates :first_name, presence: true
enum role: [ :flyer, :admin ]
def valid_email?
email_checker
end
private
def email_checker
self.email.match(/^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/)
end
end
This is my test:
test "if a user has an invalid email, cannot be saved" do
user = build(:user)
user1 = build(:user, email: "here#here#here")
user2 = build(:user, email: "here.here#here")
assert user.save
refute user1.save
refute user2.save
end
The email_checker method does return nil if email is either here#here#here or here.here#here. So what is going on?
Because you just call self.email.match method. If you want to validate filed you should use or create validator.
In your case you can create own custom validator or use e-mail validator from gems (i.e email_validator).
I have pretty big RoR app.
There is superclass named User.
class User < ActiveRecord::Base
validates :email, presence: true
end
Also I have class Client which inherited by User
class Client < User
with_options(on: [:personal_info]) do |pi|
pi.validates :first_name,
:last_name,
:email,
:mobile_phone,
:landline_phone,
presence: true
pi.validates :primary_email,
email_format: {
message: "doesn't look like an email address"
}
end
end
When I create Client's object I got 2 errors that "Email can't be blank."
How can I disable or skip validates of superclass??
Remove validations in superclass is impossible.
In my user model i have validation of password and an instance method like this:
class User < ActiveRecord::Base
validate :email ......
validates :password, length: { minimum: 6 }
def my_method
# .....
# save!
end
end
As you can see inside this method i have a call to the save! method which save the user after altering some fields, so i want to skip the validation of password but not other validations only when i call my_method on a user instance , how i can do this please ? thank you
I find the solution if someone is interesting, i simply add attr_accessor :skip_password_validation to my model, then i add a condition to my password validation validates :password, length: { minimum: 6 }, unless: :skip_password_validation, and when i call my_method in the controller with an instance of user model, i set this attribute above with true. it's all , here what the user model will look like:
class User < ActiveRecord::Base
validate :email ......
validates :password, length: { minimum: 6 }, unless: :skip_password_validation
attr_accessor :skip_password_validation
def my_method
# .....
# save!
end
end
In the controller before i call user.my_method i just add the line : user.skip_password_validation = true.
I hope this help you :)
You can do it with 2 methods.
model.save(:validate => false)
See here and here
OR
Skipping the Callback
skip_callback :validate, :before, :check_membership, :if => lambda { self.age > 18 }
API Doc
My User model has an attribute called :profile_name which is used in routing profile page url's - domain.com/:profile_name . In order to prevent collision with my other views I want to make sure a User can't choose something like "friends" or "feed" as their profile name. How can I set this in validations?
/models/user.rb (currently):
...
validates :email, presence: true, uniqueness: true
validates :profile_name, presence: true,
uniqueness: true,
format: {
with: /^[a-zA-Z0-9_-]+$/,
message: 'Must be formatted correctly.'
}
...
The exclusion validation helper:
validates :profile_name, presence: true,
...,
exclusion: {
in: ["friends", "feed"],
message: "Profile name %{value} is reserved."
}
Use a custom validation method. You'd probably want to separate out the forbidden list, but I kept this extra concise.
class User < ActiveRecord::Base
validates :profile_not_forbidden
protected
def profile_not_forbidden
if ['friends','feed'].include?(profile_name)
errors.add(:profile_name, 'Forbidden profile name.')
end
end
end