39

On Rails 5.

I have an Order model with a description attribute. I only want to validate it's presence if one of two conditions is met: if the current step is equal to the first step OR if require_validation is equal to true.

I can easily validate based on one condition like this:

validates :description, presence: true, if: :first_step?

def first_step?
 current_step == steps.first
end

but I am not sure how to go about adding another condition and validating if one or the other is true.

something like:

validates :description, presence: true, if: :first_step? || :require_validation

Thanks!

5 Answers 5

79

You can use a lambda for the if: clause and do an or condition.

validates :description, presence: true, if: -> {current_step == steps.first || require_validation}
Sign up to request clarification or add additional context in comments.

1 Comment

Beautiful solution.
17

Can you just wrap it in one method? According to the docs

:if - Specifies a method, proc or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

validates :description, presence: true, if: :some_validation_check

def some_validation_check
    first_step? || require_validation
end

Comments

3

You can pass a lambda to be evaluated as the if condition.

Try:

validates :description, presence: true, if: -> { first_step? || require_validation }

3 Comments

Isn't that a lambda? A block would be: validates :description, presence: true, if: { first_step? || require_validation }
Ah, you are right. I should have said "You can pass a lambda".
:) A block also works though. Rails just converts it to a proc or lambda (I forget what) before using it.
1

If you don't want to add one method as Jared say then you can try use lambda

validates :description, presence: true, if: ->{ first_step? || require_validation }

Comments

1

If you have a lot case , you can design for validates

validates_presence_of :price_tech_fee, if: :price_tech_fee_require?, :message => :required

validates_presence_of :percentage_tech_fee, if: :percentage_tech_fee_require?, :message => :required

def percentage_tech_fee_require?
    is_active? && is_transaction_percentage? && is_premium?
  end

def is_active?
  !self.is_deleted && self.is_active
end

def is_transaction_percentage?
 self.is_per_transaction && self.is_percentage
end

def is_premium?
  ....
end

1 Comment

Convention says that you shouldn't define a method that is called "is_,,," if it should return a boolean value. Just use "?" at the end (like you did).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.