Is there a way to retrieve failed validations without checking the error message?
If I have a model with validates :name, :presence => true, :uniqueness => true, how can I check if determine what validation failed(was it uniqueness or was it presence?) without doing stuff like:
if error_message == "can't be blank"
# handle presence validation
elsif error_message = "has already been taken"
# handle uniqueness validation
end
There's a relatively new method that let you do just that, it's not documented anywhere as far as I know and I just stumbled on it while reading the source code, it's the #added? method:
person.errors.added? :name, :blank
Here's the original pull request: https://github.com/rails/rails/pull/3369
ActiveModel::Errors is nothing more than a dumb hash, mapping attributes names to human-readable error messages. The validations (eg. the presence one) directly add their messages to the errors object without specifying where they came from.
In short, there doesn't seem to be an official way of doing this.
You can Haz all your errors in the errors method. Try this on an saved unvalid record :
record.errors.map {|a| "#{a.first} => #{a.last}"}
Related
Is there an elegant way to call a method when a specific ActiveRecord validation fails? I'm envisioning something like...
validates :email_address, :uniqueness => true, :when_fail => :call_method
I have a roundabout way of calling the method when the validation fails involving code in my controller, but I'm looking for something more straight-forward within the model. I can't find any relevant examples online.
EDITED out other details to focus on the question.
What about this in model?
Model < ActiveRecord::Base
after_validation do
self.my_method unless self.errors.empty?
end
end
For specific validation you can use http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-5B-5D.
I have a model that has
attr_accessible :name, :activity
validates :name, uniqueness: { scope: :activity }
It works and it doesn't allow the creation of duplicate entries. But with simple_form it only shows the error on the :name field. I'd like it to have errors on both fields saying that this 'name' and 'activity' combination has already been taken.
I'm thinking I need to create a custom validation method, but I'm hoping there's a more elegant solution that I've overlooked so far.
Is there a way to show errors on both these fields?
You can add another validation on :activity so that it will be marked as duplicate as well:
validates :activity, uniqueness: { scope: :name }
I'm not sure that's the most elegant solution but it will spare you the custom validation method.
I ended up doing
validates :name, uniqueness: { scope: :activity, message: 'This name and activity combination has already been taken.' }
I haven't decided if I'm going to have it validate both and put the message on both fields yet, but that opposite for the :activity field would be the same.
I would like to show some extra info in error messages resulting from a failed validation. For example suppose I have a class Book with the following validation
validates :name, presence: true, uniqueness: true
When someone tries to insert a book by the same name the following error message is returned
{"name":["has already been taken"]}
Instead I wanna show
{"name":["Book 'Great Expectaions' has already been taken at id:7"]}
Right now to make this happen I have to remove the uniqueness validation that I mentioned above and do the following
validate do |book|
existing_book = Book.find_by_name(book.name)
if existing_book
book.errors.add(:name, "#{existing_book.name} already exists at id: #{existing_book.id}")
end
end
Is there a way to get custom error messages like above without writing a custom uniqueness validation? I was thinking something along the lines of
validates :name, presence: true, uniqueness: {message: "#{self.name} already exists at id: #{Book.find_by_name(self.name).id}"
But this does not seem to work as self.name returns 'Book'. Is there a way to access the passed parameters in this context?
You'll have to do this as a custom validation. I would do it like so:
validate :name_is_unique
private
def name_is_unique
errors.add(:name, "#{other_book.name} already exists at id: #{other_book.id}") if other_book = Book.find_by_name(name)
end
The issue isn't really that you can't include the current model attributes in your validation, its that there's no 'one-liner' way to include another model. The good news is, that's what the validate method is for.
If it bothers you to have this in your model, just write a custom validator so it can be re-used application-wide.
My New Contract Form use to work ... it still needs some refinement ... but the current version use to work, but now I am getting this message:
3 errors prohibited this codeline from being saved:
There were problems with the following fields:
Contract can't be blank
Client can't be blank
Code can't be blank
I do not have any fields named Contract, Client, or Code ... those are my models.
Here is the params which I raised in the codelines_controller:
{"contract_attributes"=>{"authnum"=>"900700", "st_date"=>"2012-09-03",
"end_date"=>"2012-12-31"}, "client_attributes"=>{"f_name"=>"Esme", "mi"=>"J",
"l_name"=>"Inneed", "birth_date"=>"1986-03-18", "address1"=>"62 Southy View",
"address2"=>"", "city"=>"Fromm", "zip_code"=>"55803", "state"=>"WI",
"medicare_num"=>"3008769788", "medicaid_num"=>"765894567", "member_num"=>"6709875-3",
"soc_sec_care_mgr"=>"Caring Manager", "sscm_ph"=>"1-444-444-4444",
"nurse_care_mgr"=>"Caring Nurse", "ncm_ph"=>"1-555-555-5555", "emer_contact"=>"Always
Here", "ec_ph"=>"1-666-666-6666", "pri_care_phy"=>"The One",
"pcp_ph"=>"1-777-777-7777"}, "code_attributes"=>{"code_name"=>"S-5463",
"status"=>"Active", "description"=>"Transition from schl to work"},
"units_alloc"=>"100.00"}
as you can see all of the fields that need data have data and are not 'blank'
I did contract out to see if I could get a professional to help me design a button to add extra attributes to the form, but I had to cancel the contract because they were not communicating. So part of this process required that I make them collaborators to github and heroku. Maybe they had to change something to work on the project?
Can someone give me some guidance on how to resolve this issue?
Thanks.
look in app/models/theModelThatIsUsed.rb and if you find something like:
validates :contract, :presence => true
validates :client, :presence => true
validates :code, :presence => true
delete that lines
I have a following code:
validates :name, :presence => true
Error message produced is "Name can't be blank"
Instead of using the actual attribute name (in this case "name") I want to
display message as "Registration name can't be blank".
How do I overwrite the default message on the validations? I tried appending :message
but it didn't work...
Thanks!
In en.yml file define custom keys as:
activerecord:
attributes:
model_name:
attribute_name1: key1
attribute_name2: key2
......
This key will be used automatically when errors are generated.
Reference: http://edgeguides.rubyonrails.org/i18n.html#translations-for-active-record-models
(5.1 Translations for Active Record Models)
This will do the trick:
validates :name, presence: { message: "Registration name can't be blank" }
or the old hash rocket syntax version:
validates :name, :presence => { :message => "Registration name can't be blank" }
Its a little late now (after about 35 days) to answer this. So, sorry for this. But just wanted to share that I had used a gem, more than a few months back, for custom error messages.
This plugin allows you to omit the attribute name for specific messages. All you have to do is begin the message with a ‘^’ character.
I just checked it at
https://github.com/nwise/custom_error_message
& it has not been updated since march. So, i probably used it at the right time.
ps : Your answer for defining the custom keys in the yml file is more appropriate though.