I have an invoice model with approver_note, po_number and state_id.
I need validations to check:
validates :approver_note, :presence => true, {:scope => state_id == 3}
validates :po_number, :presence => true, {:scope => state_id ==2}
So, if the user selects state_id = 3, he must enter a note. If he selects state_id = 2, he must enter a po_number.
Any assistance would be great... thanks!
Luckily, Rails has got us covered with a handy feature called validation scopes. The scope option to the Rails uniqueness validation rule allows us to specify additional columns to consider when checking for uniqueness. This rule says that “the name of this project must unique, within the scope of this account”.
To verify whether or not an object is valid, Rails uses the valid? method. You can also use this method on your own. valid? triggers your validations and returns true if no errors were found in the object, and false otherwise. class Person < ActiveRecord::Base validates :name, :presence => true
Callbacks and observers allow you to trigger logic before or after an alteration of an object’s state. Before you dive into the detail of validations in Rails, you should understand a bit about how validations fit into the big picture.
Because every application handles this kind of thing differently, Rails does not include any view helpers to help you generate these messages directly. However, due to the rich number of methods Rails gives you to interact with validations in general, you can build your own.
You're looking for the :if
option instead of :scope
.
validates :approver_note, :presence => true,
:if => lambda { |invoice| invoice.state_id == 3 }
But since a lambda is a little ugly, I'd probably add a method to encapsulate what you're doing a bit better:
validates :approver_note, :presence => true, :if => :requires_note?
validates :po_number, :presence => true, :if => requires_po_number?
def requires_note?
state_id == 3
end
def requires_po_number?
state_id == 2
end
If you actually have a bunch of different attributes that are required when state_id
is 3, not just a note, then you may want something like this:
validates :approver_note, :presence => true, :if => :green_state?
validates :po_number, :presence => true, :if => orange_state?
def green_state?
state_id == 3
end
def orange_state?
state_id == 2
end
(Replace "green" with -- I dunno -- "high_documentation" or whatever makes sense in your world.)
Or maybe you want to let the state decide what it is:
def green_state?
state.green?
end
It really does help to make the terminology in your code adhere more closely to your real-world language, as opposed to "3" and "2".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With