Rails - How to add validation on callback - ruby-on-rails

I need to add validation on a before_validation model filter. How can I do that?
Thanks in advance
--
EDIT
I didn't express myself correctly. I need to add validation on a callback like that:
validate :check_length
def check_length
if my_conditional
validates_length_of :name, :minimum => 5
else
validates_length_of :name, :minimum => 7
end

You will have to create a method and call it from the callback
before_validation :run_this_check
def run_this_check
##run your validation
errors.add(:key, "This is your error message")
end
or if the validation is not dealing with an attribute (or field)
def run_this_check
errors.add_to_base('error message')
end

try using
class X < ActiveRecord
validates_length_of :name, :minimum => 5 if my_condition
validates_length_of :name, :minimum => 7 unless my_condition
end
what's the condition?

Related

How do I use an if statement in Rails validation?

I'm trying to create a validation statement that validates an object if service_area is present UNLESS service_area_radius==0
Here's the statement I created, which doesn't work:
validates :service_area, :presence => true, unless: "service_area_radius==0"
http://railscasts.com/episodes/41-conditional-validations
Like this:
validates_presence_of :password, :if => :should_validate_password?
validates_presence_of :country
validates_presence_of :state, :if => :in_us?
attr_accessor :updating_password
def in_us?
country == 'US'
end
def should_validate_password?
updating_password || new_record?
end
validates :service_area,
presence: {message: "Area Radius is missing."}, if: :radius_found?
private
def radius_found?
service_area_radius > 0
end
The validation for service_area will be executed if radius_found? returns true.
radius_found? will return true when the service_area_radius(attribute) hold value > 0.
Adding a custom message with message: option, when the validation fails.

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.

before_save not working with Rails 3

I have this Project model:
class Project < ActiveRecord::Base
validates :status, :inclusion => { :in => ['active', 'closed'] }
validates :title,
:presence => true,
:length => { :in => 4..30 }
before_save :set_default_status_if_not_specified
private
def set_default_status_if_not_specified
self.status = 'active' if self.status.blank?
end
end
If I create a new object like this:
Project.create!(:title => 'Test 2', :pm_id => 1)
I get these errors: Validation failed: Status is not included in the list
But status field should get filled in before save.
That's because it validates before before_save.
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
(-) save
(-) valid
(1) before_validation
(-) validate
(2) after_validation
(3) before_save
(4) before_create
(-) create
(5) after_create
(6) after_save
(7) after_commit
You could try before_validation ?
It looks like validation happen before the before_save callbacks. Perhaps you want to try before_validation instead?

How to validate a single attribute for a submitting ActiveRecord instead of all its attributes?

I am using Ruby on Rails 3 and I would like to validate a single attribute for a submitting ActiveRecord instead of all its attributes.
For example, in my model I have:
validates :firstname, :presence => true, ...
validates :lastname, :presence => true, ...
I would like to run validation on the :firstname and on the :lastname separately. Is it possible? If so, how can I make that?
P.S.: I know that for validation purposes there are methods like "validates_presence_of", "validates_confirmation_of", ..., but I would like to use only the above code.
You can setup a virtual attribute on your model, and then do conditional validation depending on that attribute.
You can find a screencast about this at http://railscasts.com/episodes/41-conditional-validations
class Model < ActiveRecord::Base
def save(*attrs)
Model.validates :firstname, :presence => true if attrs.empty? || attrs.include?( :firstname )
Model.validates :lastname, :presence => true if attrs.empty? || attrs.include?( :lastname )
...
super
end
end
m = Model.new
m.save
#=> false
m.save(nil) # same as save(false), you can use both of them
#=> true
m = Model.new :firstname => "Putty"
m.save
#=> false
m.save(:firstname, :lastname)
#=> false
m.save(:firstname)
#=> true
You can just delete the second line of your code above so it reads:
validates :firstname, :presence => true
No validation will then be performed on the :lastname.
Regards
Robin

How to update attributes without validation

I've got a model with its validations, and I found out that I can't update an attribute without validating the object before.
I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
My announcement model have the following validations:
validates_presence_of :title
validates_presence_of :description
validates_presence_of :announcement_type_id
validate :validates_publication_date
validate :validates_start_date
validate :validates_start_end_dates
validate :validates_category
validate :validates_province
validates_length_of :title, :in => 6..255, :on => :save
validates_length_of :subtitle, :in => 0..255, :on => :save
validates_length_of :subtitle, :in => 0..255, :on => :save
validates_length_of :place, :in => 0..50, :on => :save
validates_numericality_of :vacants, :greater_than_or_equal_to => 0, :only_integer => true
validates_numericality_of :price, :greater_than_or_equal_to => 0, :only_integer => true
My rake task does the following:
task :announcements_expiration => :environment do
announcements = Announcement.expired
announcements.each do |a|
#Gets the user that owns the announcement
user = User.find(a.user_id)
puts a.title + '...'
a.state = 'deactivated'
if a.update_attributes(:state => a.state)
puts 'state changed to deactivated'
else
a.errors.each do |e|
puts e
end
end
end
This throws all the validation exceptions for that model, in the output.
Does anybody how to update an attribute without validating the model?
You can do something like:
object.attribute = value
object.save(:validate => false)
USE update_attribute instead of update_attributes
Updates a single attribute and saves the record without going through the normal validation procedure.
if a.update_attribute('state', a.state)
Note:- 'update_attribute' update only one attribute at a time from the code given in question i think it will work for you.
try using
#record.assign_attributes({ ... })
#record.save(validate: false)
works for me
Yo can use:
a.update_column :state, a.state
Check: http://apidock.com/rails/ActiveRecord/Persistence/update_column
Updates a single attribute of an object, without calling save.
All the validation from model are skipped when we use validate: false
user = User.new(....)
user.save(validate: false)
Shouldn't that be
validates_length_of :title, :in => 6..255, :on => :create
so it only works during create?

Resources