Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

validates associated with model's error message

I have two model as follows

class User < ActiveRecord::Base  validates_associated :account end  class Account < ActiveRecord::Base    belongs_to :user    #----------------------------------Validations--Start-------------------------   validates_length_of :unique_url, :within => 2..30 ,:message => "Should be atleast 3 characters long!"   validates_uniqueness_of :unique_url ,:message => "Already Taken"   validates_format_of :unique_url,:with => /^([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])$/ , :message => " Cannot contain special charaters"   #----------------------------------Validations--End--------------------------- end 

Now when I associate an account to a user it says

"Account is invalid"

Instead I want to get the error message directly from that model. so it should say

"Should be atleast 3 characters long!" or "Already Taken" or " Cannot contain special charaters"

is there a way to do this ?

I don't want to give a generic message like :

validates_associated :account , :message=>"one of the three validations failed" 
like image 338
Gaurav Shah Avatar asked Sep 12 '11 11:09

Gaurav Shah


People also ask

What is validation error message?

The Validation Error Message property lets you define a custom error message to display if the validation checks specified in the Validation (Regex) fails.

What causes validation error?

Validation errors typically occur when a request is malformed -- usually because a field has not been given the correct value type, or the JSON is misformatted.

What are validations in Rails?

Rails validation defines valid states for each of your Active Record model classes. They are used to ensure that only valid details are entered into your database. Rails make it easy to add validations to your model classes and allows you to create your own validation methods as well.


2 Answers

You can write your own custom validator, based on the code for the built-in validator.

Looking up the source code for validates_associated, we see that it uses the "AssociatedValidator". The source code for that is:

module ActiveRecord   module Validations     class AssociatedValidator < ActiveModel::EachValidator       def validate_each(record, attribute, value)         if Array.wrap(value).reject {|r| r.marked_for_destruction? || r.valid?}.any?           record.errors.add(attribute, :invalid, options.merge(:value => value))         end       end     end      module ClassMethods              def validates_associated(*attr_names)         validates_with AssociatedValidator, _merge_attributes(attr_names)       end     end   end end 

So you can use this as an example to create a custom validator that bubbles error messages like this (for instance, add this code to an initializer in config/initializers/associated_bubbling_validator.rb):

module ActiveRecord   module Validations     class AssociatedBubblingValidator < ActiveModel::EachValidator       def validate_each(record, attribute, value)         ((value.kind_of?(Enumerable) || value.kind_of?(ActiveRecord::Relation)) ? value : [value]).each do |v|           unless v.valid?             v.errors.full_messages.each do |msg|               record.errors.add(attribute, msg, options.merge(:value => value))             end           end         end       end     end      module ClassMethods       def validates_associated_bubbling(*attr_names)         validates_with AssociatedBubblingValidator, _merge_attributes(attr_names)       end     end   end end 

So you can now validate like so:

class User < ActiveRecord::Base  validates_associated_bubbling :account end 

Also, be sure to add a validate: false in your has_many association, otherwise, Rails will validate the association by default and you'll end up with two error messages, one given by your new AssociatedBubblingValidator and one generic given by Rails.

like image 98
Ben Lee Avatar answered Oct 09 '22 13:10

Ben Lee


May be you can try something as given below

validates_associated :account , :message=> lambda{|class_obj, obj| obj[:value].errors.full_messages.join(",") } 

Through obj[:value] you're accessing the validated Account object. So will obj[:value].errors give you errors.

like image 27
PaulDaviesC Avatar answered Oct 09 '22 13:10

PaulDaviesC