Custom validation :on => :create not working - ruby-on-rails

I have a custom validation method that I only want executed on create:
validate :post_count, :on => :create
def post_count
# validate stuff
end
However, it's getting fired on update (in addition to on create).
Does the :on => :create option not work with custom validation methods?

As far as I know, there's no :on option. Use
validate_on_create :post_count
instead. And there's validate_on_update also. You can read about this methods here.

This may be a Rails 2.x vs. Rails 3 issue but according to the Rails Guides on Validation the :on option is definitely valid (though I am fighting with why it's not firing for me in a similar way).

Related

Validating password with validates_format_of

EDIT: I realized the comments about there not being a difference with :save already covered were correct, and was able to work through some errors. However, it still appears the regex validation is failing for :password.
I'm a little confused, and think the problem might be related to there being only :password_digest in the table itself, while we use password and password_confirmation as attributes in the model. But I'm also guessing Rails has this all worked out and takes care of everything with the has_secure_password function.
validates_format_of :password, :with => /\A[a-zA-Z]\z/, :on => :create, :update fails with the string password.
Obviously, this doesn't make sense and matches fine in the console (using =~ or .match(). Also notice if I set allow_nil: true for :password other tests involving the user start failing (which doesn't make sense, as the password should never be nil anyways).
I don't see any use case where you need on create and update together if on: :save is already there.
For more model callbacks please refer this.
According to rails docs
The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use on: :create to run the validation only when a new record is created or on: :update to run the validation only when a record is updated.
So, you should not use :on option in your validation

rails validates_uniqueness_of not working as it should

I have an account model like so
class Account < ActiveRecord::Base
end
I had some duplicates records on it in production so I've added this line to it
validates_uniqueness_of :owner_id, :on => :create
so it will only verify this on new records and NOT on save!
it works on localhost and even on console on production.
but I have a job that runs every 10 minutes that uses rails runner and it fails for
Validation failed: Owner has already been taken (ActiveRecord::RecordInvalid)
The runner does some actions on accounts and then saves them.
am I doing something wrong on this syntax ?
Only time I've seen this happen was when a controller "create" action was being sent as a :get request (instead of :post as it should be in REST). The result was the validation didn't realize it was doing a :create. Doesn't sound like what you've got here... but maybe similar?
FYI my fix at the time was to use if: :new_record? instead of on: :create until the request type could be fixed. You could try this.
Also, you can put a debug statement into the validation to interrogate the state of the object during that validation with e.g. if: -> { binding.pry } or if: -> { debugger } (depending on what you use to debug with, of course). Hopefully that will help figure out what the runner is doing different. You can ask the object if it's a new_record? or what changes it has to save, etc.
I have found that this method has no
:on => :create
only :if
so I've did this:
validates_uniqueness_of :owner_id, :if => Proc.new { |account| account.created_at > Time.now - 10.seconds }

Validation only in specific form

Is there any way to trigger validation only in specific forms(controller's action), not globally at every save or update?
Something like User.create(:validate=>true) flag.
Yes, you can supply conditionals to the validations, eg:
validates_presence_of :something, :if => :special?
private
def make_sepcial
#special = true
end
def special?
#special
end
Now all you have to do to turn on these validations is:
s = SomeModel.new
s.make_special
As you explained in the comments, you want to skip validation for new records. In that case, you can use thomasfedb's answer, but don't use the #special variable, but:
validates_presence_of :something, :if => :persisted?
This will validate only for saved Users, but not for new Users. See the API documentation on persisted?.
This is a bit old. But I found http://apidock.com/rails/Object/with_options to be a good way of handling this sort of behaviour.

Specifying two conditions with :if

I have a model which validates presence of an attribute if a check box is checked in the view.
The code is something like this:
validates_presence_of :shipping_first_name, :if => :receive_by_email_is_unchecked
I am looking to have another condition of this validation.So how do I go about doing this ??
My assumption is that something like this would do:
validates_presence_of :shipping_first_name, :if => {:receive_by_email_is_unchecked,:form_first_step_validation}
I am not sure if this is the write way of doing it or not ??
Any suggestions would be appreciated.
You can pass method names in an array:
validates_presence_of :shipping_first_name, :if => [:receive_by_email_is_unchecked, :form_first_step_validation]
Alternatively you can use proc if you don't want to define separate methods just for conditioning validations:
validates_presence_of :shipping_first_name, :if => proc { !receive_by_email? && form_first_step_validation }
I don't think that will work, but have a look at the source code for validates_presence_of https://github.com/rails/rails/blob/master/activemodel/lib/active_model/validations/presence.rb
You can build your own validator to do exactly that
Ryan Bates covered this in one of his first Rails casts
http://railscasts.com/episodes/41-conditional-validations
It's still valid although syntax may be slightly different for Rails v 3 +
I assume you are working on a Rails 2.x app as the syntax you use is not Rails 3 syntax
Rails 3.x syntax would be
validates :field_1, :field_2, :presence_of => true, :if => # Use a proc, or an array of conditions here. see the valid examples and comments that you have already received for this question from #jimworm and #Michał Szajbe

Executing custom validation before record created?

I want to execute a custom validation before the record is created?
It looks as if this is the right method: before_validation_on_create. For example:
before_validation_on_create :custom_validation
But am not sure. Any help would be appreciated.
In rails 3
before_validation_on_create :do_something
has been replaced with:
before_validation :do_something, :on => :create
before_validation_on_create hooks happen before validation on create… but they aren't validations themselves.
What you probably want to do is use validate and a private method which adds to the error array. like this:
class IceCreamCone
validate :ensure_ice_cream_is_not_melted, :before => :create
private
def ensure_ice_cream_is_not_melted
if ice_cream.melted?
errors.add(:ice_cream, 'is melted.')
end
end
end
The following worked for me in Rails 5:
validate :custom_validation_method, :on => :create
Running
validate :custom_validation_method, :before => :create
gave me following error:
Unknown key: :before. Valid keys are: :on, :if, :unless, :prepend.
There's a great resource here for information on callbacks and the order they happen in:
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Resources