multiple validations based on action with rails - ruby-on-rails

how can have different validations depending on the action?
validates :total_pressed,
:numericality => { :on => :create, :greater_than => 0 },
:numericality => { :on => :update, :greater_than_or_equal_to => 100 }
the first numericality statement is ignored

You can use validate_on_create and validate_on_update
def validate_on_create # is only run the first time a new object is saved
errors.add(:total_pressed, 'invalid number') if total_pressed < 0
end
def validate_on_update
errors.add(:total_pressed, 'invalid number') if total_pressed < 100
end

In you validate first numericality statement is ignored because it`s hash and one thing rewrite another
You can do this:
validates :total_pressed, :numericality => { :on => :create, :greater_than => 0 }
validates :total_pressed, :numericality => { :on => :update, :greater_than_or_equal_to => 100 }

Generally the validation operates on both create and update (via save), so if you pass the on flag then you'll limit it to either of the two methods. If you want to have different validation based on the action, then you're best off using a custom validation.
i.e
validate :total_pressed_on_create, :total_pressed_on_update
def total_pressed_on_create
errors.add(:total_pressed, 'invalid number') if self < 0 and self.new_record?
end
def total_pressed_on_update
errors.add(:total_pressed, 'invalid number') if self < 100 and !self.new_record?
end
Something along those lines. Check Rails Guide: Validation for more details.

Related

Validation not working on Ranges?

Can someone explain to me why my validation won't get triggered when I submit a string such as "foo" to number?
class Course < ActiveRecord::Base
validates :number, :inclusion => 0..100
end
Only when I change my code to this...
class Course < ActiveRecord::Base
validates :number, :inclusion => 0..100, :numericality => true
end
... the validation gets triggered.
Is this a Rails bug or am I missing something really fundamental here?
I am using Rails 4.2.0 by the way.
It's because rails is converting the string to a number (assuming you've got it persisted as an integer) before doing the validation. If you call to_i on a string you get 0 which is valid for your range.
For example:
> c = Course.new
> c.number = 'hi'
> c.number
=> 0
> c.valid?
=> true
The reason the numericality validators is triggering when you add it is, I think, because it checks the value before any type casting happens:
> c.number = 'hi'
> c.number_before_type_cast
=> 'hi'
Please try this:
validates_numericality_of :number, :only_integer => true,
:greater_than_or_equal_to => 1,
:less_than_or_equal_to => 99,
:message => "can only be number between 1 and 100."
ref: http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_numericality_of
This turned out to work best for me:
class Course < ActiveRecord::Base
validates :number, :numericality => { :greater_than_or_equal_to => 0, :less_than_or_equal_to => 100 }
end

Rails Models Validation 1 Word

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

Different types of validations in rails

I have a User model
is there a difference between
class User < ActiveRecord::Base
validates :name, :presence => true
end
and
class User < ActiveRecord::Base
def validate
errors.add_to_base "name should not be nil" if name.nil?
end
end
The validates macro is more flexible, as it also allows you to do things like:
validates :name, :format => { :with => /\A[a-zA-Z]+\z/,
:message => "Only letters allowed" }, :length => { :in => 6..20 }
The validate method is really a quick and easy way to do custom validations when existing ones do not exist. (When custom validations get too complex, then you should usually move them into custom validators and use the validates macro).
See more at http://guides.rubyonrails.org/active_record_validations_callbacks.html
Yes -- the first will fail to save an empty string, whereas the second will allow it.

validates in rails

I have a model with valid data; everything works.
In the form, I select as how to select the option I choose I want to be valid also 2 fields
validates_presence_of :is_ranking, :on => :update
validates :awards_count, :on => :update, :unless => :is_ranking == 1
Now as is_ranking == 1 to check again: awards_count
All sent from a form before being added to the database
How do I force rails to valid these two additional fields on the form I choose to rip options in select?
you should use symbol or string with :if and :unless
Try to replace condition with method
validates :awards_count, :on => :update, :unless => :is_ranking?
# You actually don't need that method in case your `is_ranking` field is `boolean`.
def is_ranking?
is_ranking == 1
end
Or with string
validates :awards_count, :on => :update, :unless => "is_ranking?"

Rails 3 - how to skip validation rule?

I have for the registration form this validation rule:
validates :email,
:presence => {:message => 'cannot be blank.'},
:allow_blank => true,
:format => {
:with => /\A[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]+\z/,
:message => 'address is not valid. Please, fix it.'
},
:uniqueness => true
This rule check, if a user fill into the registration form email address (+ its correct format).
Now I am trying to add the opportunity to log in with using Twitter. Twitter doesn't provide user's email address.
How to skip in this case the validation rule above?
You can skip validation while saving the user in your code. Instead of using user.save!, use user.save(:validate => false). Learnt this trick from Railscasts episode on Omniauth
I'm not sure whether my answer is correct, just trying to help.
I think you can take help from this question. If i modify the accepted answer for your question, it will be like (DISCLAIMER: I could not test the following codes as env is not ready in the computer i'm working now)
validates :email,
:presence => {:message => 'cannot be blank.', :if => :email_required? },
:allow_blank => true,
:format => {
:with => /\A[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]+\z/,
:message => 'address is not valid. Please, fix it.'
},
:uniqueness => true
def email_required?
#logic here
end
Now, you update the email_required? method to determine whether it is from twitter or not! If from twitter, return false otherwise true.
I believe, you need use same :if for the :uniqueness validator too. otherwise it will. Though, i'm not sure too :(. Sorry
Skipping Individual Validations
Skipping individual validations requires a bit more work. We need to create a property on our model called something like skip_activation_price_validation:
class Product < ActiveRecord::Base
attr_accessor :skip_activation_price_validation
validates_numericality_of :activation_price, :greater_than => 0.0, unless: :skip_activation_price_validation
end
Next we will set the property to true any time we want to skip validations. For example:
def create
#product = Product.new(product_params)
#product.skip_name_validation = true
if #product.save
redirect_to products_path, notice: "#{#product.name} has been created."
else
render 'new'
end
end
def update
#product = Product.find(params[:id])
#product.attributes = product_params
#product.skip_price_validation = true
if #product.save
redirect_to products_path, notice: "The product \"#{#product.name}\" has been updated. "
else
render 'edit'
end
end
You seem to be doing two separate validations here:
If a user provides an email address, validate it's format and uniqueness
Validate the presence of an email address, unless it's a twitter signup
I would do this as two separate validations:
validates :email,
:presence => {:message => "..."},
:if => Proc.new {|user| user.email.blank? && !user.is_twitter_signup?}
validates :email,
:email => true, # You could use your :format argument here
:uniqueness => { :case_sensitive => false }
:unless => Proc.new {|user| user.email.blank?}
Additional info: validate email format only if not blank Rails 3
The best way would be:
It would validate the email when the user is not signed in from twitter as well as skip email validation when signed from twitter.
validates :email,
:presence => {:message => 'cannot be blank.'},
:allow_blank => true,
:format => {
:with => /\A[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]+\z/,
:message => 'address is not valid. Please, fix it.'
},
:uniqueness => true
unless: Proc.new {|user| user.is_twitter_signup?}

Resources