简体   繁体   中英

Rails 4: remove attribute name from error message in custom validator

In my Rails 4 app, I implemented a custom validator named LinkValidator on my Post model:

class LinkValidator < ActiveModel::Validator

  def validate(record)
    if record.format == "Link"
      if extract_link(record.copy).blank?
        record.errors[:copy] << 'Please make sure the copy of this post includes a link.'
      end
    end
  end

end

Everything works fine, except that currently, the message displayed is:

1 error prohibited this post from being saved:
Copy Please make sure the copy of this post includes a link.

How can remove the word "copy" from the above message?

I tried record.errors << '...' instead of record.errors[:copy] << '...' in the validator, but then the validation no longer works.

Any idea?

Unfortunately currently the format of full_messages for errors is controlled with a single I18n key errors.format , hence any change to it will have a global consequences.

Common option is to attach error to the base rather than to the attribute, as full messages for base errors do not include attribute human name. Personally I don't like this solution for number of reason, main being that if the validation error is caused by a field A, it should be attach to field A. It just makes sense. Period.

There is no good fix for this problem though. Dirty solution is to use monkey patching. Place this code in a new file in your config/initializers folder:

module ActiveModel
  class Errors
    def full_message(attribute, message)
      return message if attribute == :base
      attr_name = attribute.to_s.tr('.', '_').humanize
      attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
      klass = @base.class
      I18n.t(:"#{klass.i18n_scope}.error_format.#{klass.model_name.i18n_key}.#{attribute}", {
                                 :default   => [:"errors.format", "%{attribute} %{message}"],
                                 :attribute => attr_name,
                                 :message   => message
                             })
    end
  end
end

This preserves the behaviour of full_messages (as per rails 4.0), however it allows you to override the format of full_message for particular model attribute. So you can just add this bit somewhere in your translations:

activerecord:
  error_format:
    post:
      copy: "%{message}"

I honestly dislike the fact that there is no clean way to do this, that probably deserves a new gem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM