Reputation: 730
I want to validate the Discount of a Sale in my Sale model.
The form for creating a Sale receives the Product data from my Warehouse model and saves it inside the Sale record:
<%= f.select(:product, Warehouse.pluck(:product).uniq, {prompt:true}, {class: 'form-control'}) %>
The Warehouse model has the discount specified for this respective product. Now I want to check if the sale.product
is equal to the warehouse.product
and then set the discount limit for this sale. Is that possible? Something like this:
validates_length_of :discount, maximum: Warehouse.where(:product => @sales.product).pluck(:discount), message: "Discount is to high"
Many Thanks in advance!
Upvotes: 3
Views: 1421
Reputation: 9485
First of all, you should be validating numericality
for numeric values.
Custom validation is unnecessary. You don't have to use constants or literals or other class-evaluation time values! Use procs! They will be called!
You pass a key as a comparison and then a proc as a value, so it is called during validation.
valudates_numericality_of :discount,
less_than_or_equal_to: proc { |model| Something.query(whatever).pluck(:wow) },
message: "is too high"
Note: you should probably also add a check for whether it's positive.
Bonus (pure fun, best not use): almost the same code with a spectacular amount of arrows
(in order: symbol <=
, hashrocket =>
, stabby-lambda -> () {}
):
valudates_numericality_of :discount,
:<= => -> (model) { Something.query(whatever).pluck(:wow) },
:message => "is too high"
Note that 1.9 hash syntax won't work with a symbol like <=
(like <=: value
) so you have to stick to a hashrocket with this one, which is... another bit of pure fun.
Upvotes: 5
Reputation: 76774
To add to D-side
's answer (and to use this reference), you'll want to also work with the relevant data (not calling a new db query):
#app/models/sale.rb
class Sale < ActiveRecord::Base
belongs_to :product, class_name: "Warehouse", foreign_key: "product", inverse_of: :sales
validates :discount, numericality: { less_than_or_equal_to: Proc.new{|sale| sale.product.discount } }
end
#app/models/warehouse.rb
class Warehouse < ActiveRecord::Base
has_many :sales, inverse_of: :product
end
Upvotes: 0
Reputation: 3869
For this task you should use a custom validation. Please see: http://guides.rubyonrails.org/active_record_validations.html#custom-methods
Upvotes: 0
Reputation: 12320
You can try to use a custom validation
in your model
validate :maximum_discout
def maximum_discount
if Warehouse.where(:product => @sales.product).pluck(:discount).all?{|d| d > self.discount }
errors.add(:discount, "It should not cross the maximum discount")
end
end
Upvotes: 0