I'm trying to store some additional data along with the standard error message in a custom validator in Rails 3.
For example, (ignoring built-in validators) suppose I wanted to check to see if a post is a duplicate before it's saved. I might write my custom validation method like this:
class Post < ActiveRecord::Base
# prevent duplicate posts
validate do |post|
duplicates = Post.find_all_by_body(body)
errors.add_to_base("Post is a duplicate!") if duplicates.length
# something like this is desired:
# errors.add_to_base("Post is a duplicate",
# :extra => { :duplicates => duplicates })
end
end
This will let the user know there are duplicates, but along with adding the error message I would also like to store the duplicates so they can be displayed to the user. How would I store the list of duplicate posts retrieved during validation such that it is associated with the record's errors for the body field, and available to my view?
A simpler example might be length validation: If a field exceeds its maximum length, how can I store the maximum length along with an error message without simply interpolating it into the message as Rails currently does?
I have not had to do this before, but my first thought is to create a new method on the object called duplicates.
attr_accessor :duplicates
Then in your custom validate method, you can set the duplicates on the object making them available to the view when you render the errors. Notice your current code doesn't change much:
validate do |post|
duplicates = Post.find_all_by_body(body)
errors.add_to_base("Post is a duplicate!") if duplicates.size > 0
end
You would then have to intercept that error in the view manually so that you can print out all the duplicates if the "Post is a duplicate!" error is encountered.
You can pass options to the error but they are only used as substitution in i18n templates. To make a long story short, no you can't store meta-data about your error in the errors hash. If you need such a functionality you'll need to look into the ActiveModel::Errors module in Rails core.
Update: Another solution could be that instead of pushing a string into error hash, you stuff an instance of your own class, a class which quacks like a string but would be decorated with extra methods and state and such like.
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