Platform: Rail 3.0 Database: mysql 5.1
Business requirement: Only one item of a product can be issued at a time. After a return of the issued item开发者_如何学C, a new item can be issued of same product. Multiple items from different products can be issued at a time.
To implement the above business requirement, I am checking if there is already an item issued for the same product within the same date range (by checking to see if there is an overlap of the dates in my where below).
class Item < ActiveRecord::Base
validate :validate_one_item_for_product
def validate_one_item_for_product
items = Item.where( "issue_date < ? and return_date > ? and product_id = ?", return_date, issue_date, product_id)
errors.add( :base, "item already issued for this product, not returned yet") if items.size > 0
end
end
Validation defined above works fine on create but in case of update i need to implement different logic. I do not want to define two methods for same requirement. so i want to implement checks with function based upon whether its update or create operation.Is there any way i can know if operation which triggered validate is update or delete?
Simple solution is to define a method to validate it, with a parameter, and then have two validations with different :on =>
calls, that in turn call the first method with a parameter.
Also, if it helps, you might use new_record?
which will tell you if the object is being created (before it is saved)
Validations can be run at any time, not just within create
, save
, update_attributes
, etc. So even if you could know what method triggered the validation (you can hack around with the output of caller
), you should not make any use of it because it could be something completely valid yet completely unexpected.
However, all is not lost. You can check whether the record has been persisted yet by calling persisted?
.
class Item < ActiveRecord::Base
validate :validate_one_item_for_product, :unless => :persisted?
private
def validate_one_item_for_product
items = Item.where(
"issue_date < ? and return_date > ? and product_id = ?",
return_date, issue_date, product_id)
if items.size > 0
errors.add(:base,
"item already issued for this product, not returned yet")
end
end
end
精彩评论