Ruby on Rails - after_validation if valid? - ruby-on-rails

Right now, from what I know, after_validation will be called even if the model fails the validations. Is there a way to only call it if the model is valid? I tried adding return false unless self.valid? in the after_validation method but that triggers validation again and it creates an infinite loop.

The failing validations add to the errors for the record, so you could just check:
return false unless self.errors.empty?

Have you thought about using the before_save callback instead?
I believe that will only be called if the object is valid.

I know this is an old question but I ran into the same error when using a custom validation on a model I had created. Looking at the docs there's a part covering custom methods and it states that such validations are called each time the .valid? method. That's probably why the infinite loop got triggered when the :after_validation callback was triggered.

Related

when does changed? flip in activerecord callbacks?

I'm working with a Ruby on Rails application where it was authored to generate some files in the after_save callback. The paperclip gem is used in the class. When these files are created, save is called on the Ruby object which triggers a loop of this second save calling after_save which calls save which calls after_save and on and on.
save! -> after_save -> save! -> after_save!
Eventually somehow the app breaks out of this loop on its own. I'm not sure how.
My question is, if I have an attribute on a class that is changed?=true, when does changed? get flipped to false? We use a changed? check as a sort of gate to prevent this file creation from happening and it seems like changed is always true every time it enters the after_save code. I would've thought that in after_save, changed? would be false by now since the data has been saved.
You should use after_commit with a condition of the key (attribute) present in the previous_changes.
http://apidock.com/rails/ActiveModel/Dirty/previous_changes

Rails 2.3.8: Callback that will happen before save and validation (even when there's no validation)

I was using before_validation, to do a few updates to the models before they are being validated and later on - saved.
Apparently, the validation callbacks aren't called when you save without validation.
What callback should I use to make sure this code runs before the save and before validation if it exists?
Skipping validation sounds like a workaround. You're better off calling validations conditionally if there are cases when you don't want to validate. That way it's testable as well.
This seems pretty hacky but...
def save
do_something
super
end

How do change and then immediately save a Rails model instance from a validation callback?

I'm using mongoid, and I want to migrate my documents one at a time. To do this, I've tried doing the migration in an after_initialize callback, but I can't seem to save() from there without triggering the same validation and infinite recursion. Is there a better callback to use, or a different thing I should be looking at?
Have you tried passing :validate => false into the save? That allows you to bypass validations.
As per the original question,
instance.update_attributes(new_attr_hash)
will immediately save after updating the instance, but you can't bypass validations with update_attributes.
I'd use before_save, and then go through the whole collection and save them again outside the callback, instead of just initializing them like I assume you were doing before.

validates_uniqueness custom handling ROR

I would like load the particular record if it fails the validates_uniqueness constraint.
I have id (primary key) and title in my model. If the user enters a title which is already present if want to search for the record with the title and load that record instead of throwing the error.
Is there a way to do it?
You can use the before_validation callback to check validity yourself, and when it fails, trigger the behavior you're looking for. So, one way to do it would be to write code in before_validation, and in there you could do a simple .valid? call, or manually run the validation for uniqueness by itself. When validation fails, you can stop the callback chain, and trigger custom behavior.
before_validation is one of the many ActiveRecord callbacks available to you.
Another, more common way to do it would be, in your controller, instead of just saving you can basically wrap the .save call in an if statement, because .save returns false if validation fails. You can use this as a way to redirect to an alternate action, in the situation you describe.
#new_record = ThingImSaving.new(params[:thing_im_saving]
if #new_record.save
...validation has passed, continue the normal path
else
...validation has failed, do something else.
end

Is after_validation hook called every time on Active Record?

Is after_validation hook called every time, even when the validation is failed?
I tried a couple tests and it seems like it!
You're correct, the validation failure still triggers the after_validation callback. This is the order of callbacks:
before_validation
after_validation
before_save
before_create
after_create
after_save
after_commit
Also, to understand the larger chain of events: the documentation says that a "before" callback that returns false will halt the chain, and halt the action (the save, create, update, etc). An "after" callback that returns false will halt the chain of callbacks, but not the whole action.
"after_validation" is the last thing to run if validations fail, and everything is halted there. If they pass though, everything else is wrapped in a database transaction, and rolled back if something goes wrong. So your "before_create" can create a child object, for instance, and it'll be safely undone if the object creation itself fails.

Resources