diff options
Diffstat (limited to 'activerecord/lib/active_record/validations.rb')
-rw-r--r-- | activerecord/lib/active_record/validations.rb | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index c2e0c4a9ae..a9e6654aec 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -15,6 +15,86 @@ module ActiveRecord end class Errors < ActiveModel::Errors + class << self + def default_error_messages + message = "Errors.default_error_messages has been deprecated. Please use I18n.translate('activerecord.errors.messages')." + ActiveSupport::Deprecation.warn(message) + + I18n.translate 'activerecord.errors.messages' + end + end + + # Returns all the full error messages in an array. + # + # class Company < ActiveRecord::Base + # validates_presence_of :name, :address, :email + # validates_length_of :name, :in => 5..30 + # end + # + # company = Company.create(:address => '123 First St.') + # company.errors.full_messages # => + # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"] + def full_messages(options = {}) + full_messages = [] + + each do |attribute, messages| + next if messages.empty? + + if attribute == :base + messages.each {|m| full_messages << m } + else + attr_name = @base.class.human_attribute_name(attribute.to_s) + prefix = attr_name + I18n.t('activerecord.errors.format.separator', :default => ' ') + messages.each do |m| + full_messages << "#{prefix}#{m}" + end + end + end + + full_messages + end + + # Translates an error message in it's default scope (<tt>activerecord.errrors.messages</tt>). + # Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>, if it's not there, + # it's looked up in <tt>models.MODEL.MESSAGE</tt> and if that is not there it returns the translation of the + # default message (e.g. <tt>activerecord.errors.messages.MESSAGE</tt>). The translated model name, + # translated attribute name and the value are available for interpolation. + # + # When using inheritence in your models, it will check all the inherited models too, but only if the model itself + # hasn't been found. Say you have <tt>class Admin < User; end</tt> and you wanted the translation for the <tt>:blank</tt> + # error +message+ for the <tt>title</tt> +attribute+, it looks for these translations: + # + # <ol> + # <li><tt>activerecord.errors.models.admin.attributes.title.blank</tt></li> + # <li><tt>activerecord.errors.models.admin.blank</tt></li> + # <li><tt>activerecord.errors.models.user.attributes.title.blank</tt></li> + # <li><tt>activerecord.errors.models.user.blank</tt></li> + # <li><tt>activerecord.errors.messages.blank</tt></li> + # <li>any default you provided through the +options+ hash (in the activerecord.errors scope)</li> + # </ol> + def generate_message(attribute, message = :invalid, options = {}) + message, options[:default] = options[:default], message if options[:default].is_a?(Symbol) + + defaults = @base.class.self_and_descendants_from_active_record.map do |klass| + [ :"models.#{klass.name.underscore}.attributes.#{attribute}.#{message}", + :"models.#{klass.name.underscore}.#{message}" ] + end + + defaults << options.delete(:default) + defaults = defaults.compact.flatten << :"messages.#{message}" + + key = defaults.shift + value = @base.respond_to?(attribute) ? @base.send(attribute) : nil + + options = { :default => defaults, + :model => @base.class.human_name, + :attribute => @base.class.human_attribute_name(attribute.to_s), + :value => value, + :scope => [:activerecord, :errors] + }.merge(options) + + I18n.translate(key, options) + end end module Validations @@ -24,6 +104,8 @@ module ActiveRecord base.send :include, ActiveModel::Validations base.send :include, InstanceMethods + base.define_callbacks :validate_on_create, :validate_on_update + base.class_eval do alias_method_chain :save, :validation alias_method_chain :save!, :validation @@ -66,10 +148,43 @@ module ActiveRecord end end + # Runs all the specified validations and returns true if no errors were added otherwise false. + def valid? + errors.clear + + run_callbacks(:validate) + + validate if respond_to?(:validate) + + if new_record? + run_callbacks(:validate_on_create) + validate_on_create if respond_to?(:validate_on_create) + else + run_callbacks(:validate_on_update) + validate_on_update if respond_to?(:validate_on_update) + end + + errors.empty? + end + # Returns the Errors object that holds all information about attribute error messages. def errors @errors ||= Errors.new(self) end + + def get_attribute_value(attribute) + respond_to?(attribute.to_sym) ? send(attribute.to_sym) : self[attribute.to_sym] + end + + protected + + # Overwrite this method for validation checks used only on creation. + def validate_on_create + end + + # Overwrite this method for validation checks used only on updates. + def validate_on_update + end end end |