Specifying two conditions with :if - ruby-on-rails

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

Related

Rails - Where to add validation code? (Controller or Model)

I'm new to Rails, and am following this tutorial
I creates a simple model called HighScores.
I would like to customize this so that I can add a validation method for the score. I know there are shortcuts like validates_ that we can use, but for the purpose of learning, I'd like to write a method that ensures the score is between a certain range.
Where should the validate method go? In models/high_score.rb or in controllers/high_scores_controllers.rb? Or maybe in `/helpers/high_scores_helper.rb?
Validation that the model has correct data should go in the model itself. This ensures that any future attempt to save the model's data will use this validation, regardless of the path taken.
models\high_score.rb
Also -- FWIW, the validates methods aren't short cuts, they are well tested code that you should embrace and use.
The validation should go in models.
Here is an example of a range validation:
validates :score, :numericality => { :greater_than => 0 }
validates :score, :numericality => { :less_than => 100 }

How to do a simple regex validation in rails

How can perform a reguler expression to validate for either - or _ in the person username. i dont want to accept any other character like .#()$etc just - or _ so the person can either have a name like mike, mikel_mark or mike-mark. very simple. Thank you
example:
validate_format_of :username, with: "...."
The Rails 3 way to do validations is the following:
validates :username, :format => {:with => /\A[0-9a-z_]+\Z/i}
The form of validate_format_of is more Rails < 3 like and followed the "type of validation" concept, whereas the validates form is attribute based (you write all validations that apply to the attribute in one statement).
Check out the docs here: http://apidock.com/rails/v3.2.13/ActiveModel/Validations/ClassMethods/validates

Rails with_options :if => custom_method(parameterOne, parameterTwo)

I was wondering if it's possible to pass in a parameter to methods when you're using the :if option with the 'with_options' method.
For example, can I call something like this?
with_options :if => :is_user_this_level?(threshold_level) do |some_object|
some_object.validates_with ObjectValidator
end
I'm wondering if it's possible to pass in the variable 'threshold_level' to the :if option method. Basically I want to do this because I don't want to have methods like :is_user_level_two?, :is_user_level_three? and so on and so forth.
Also if there's a RAILS way of doing this and I'm barking up the wrong tree please let me know.
Thanks!
The usual :if option for ActiveRecord callbacks can take a lambda as its argument so maybe this will work:
with_options :if => ->(o) { o.is_user_this_level? threshold_level } do |some_object|
some_object.validates_with ObjectValidator
end

How to Skip Validations w/ find_or_create_by_?

Is it possible to skip validations with a dynamic find/create by method?
For example with regular save I can do something like:
p = Post.new
p.title = nil
p.body = nil
p.save(:validate => false)
Would love to do the same with find_or_create_by_title.
It dosnt look possible with the code in Rails right now however you may have better luck being a little more verbose in how you write the code. You can use find_or_initialize_by_ which creates a new object but does not save it. You can then call save with your custom options, also in the documentation they have a neat demonstration that is hard to find so I will include it below:
# No 'Winter' tag exists
winter = Tag.find_or_initialize_by_name("Winter")
winter.new_record? # true
Good luck and let me know if you need more pointers in the right direction.
For some cases, find_or_initialize_by_ will not be useful and need to skip validations with find_or_create_by.
For this, you can use below alternative flow and method of ROR:
Update your model like this:
class Post < ActiveRecord::Base
attr_accessor :skip_validation
belongs_to :user
validates_presence_of :title, unless: :skip_validation
end
You can use it now like this:
Post.where(user_id: self.id).first_or_create!(skip_validation: true)
I have used first_or_create instead of find_or_create_by here. You can pass more column names and values with this, and your validation will not be worked with this.
You can continue without any changes for strong parameters end and no need to permit this 'skip_validation' so it will work with validations while adding entries.
Using this, you can use it with and without validations by passing a parameter.
Currently skipping validation DOES work with find_or_create_by.
For example, running:
Contact.find_or_create_by(email: "hello#corsego.com).save(validate: false)
will skip a validation like:
validates :name, :email, presence: true, uniqueness: true

Rails validation :if => Proc.new or lambda?

I have found that in all examples (include rails documentation) that I have seen for the :if option of validation methods uses Proc.new instead of lambda, for example
class Foo < ActiveRecord::Base
validates_presence_of :name, :if => Proc.new{|f| .... } # why not lambda here?
end
is there any reason for this?
As far as I know, lambda
Is more strict with arguments.
Also return statement in lambda block returns from the block, not from calling function.
Both seems to be desirable behavior for :if option mentioned above, is there anything I am missing?
Both seems to be desirable behavior for :if option mentioned above, is there anything I am missing?
I'm guessing that:
It's more desirable to allow Procs as they don't care about the number of arguments. So I could easily write any of the below:
validates_presence_of :name, :if => Proc.new{|f| f.display_name.blank? } # I care about 'f' here as I need it to check something.
... and:
validates_presence_of :secret_sauce, :if => Proc.new{ MyApp::REQUIRE_SECRET_SAUCE } # I don't care about any arguments being passed in.
This may seem like a minor thing, but I guess it adds to the flexibility.

Resources