Class: AdequateErrors::Error

Inherits:
Object
  • Object
show all
Defined in:
lib/adequate_errors/error.rb

Overview

Represents one single error

Direct Known Subclasses

NestedError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base, attribute, type, options = {}) ⇒ Error

Returns a new instance of Error.



12
13
14
15
16
17
# File 'lib/adequate_errors/error.rb', line 12

def initialize(base, attribute, type, options = {})
  @base = base
  @attribute = attribute
  @type = type
  @options = options
end

Instance Attribute Details

#attributeSymbol (readonly)

Returns attribute of the object which the error belongs to.

Returns:

  • (Symbol)

    attribute of the object which the error belongs to



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/adequate_errors/error.rb', line 11

class Error
  def initialize(base, attribute, type, options = {})
    @base = base
    @attribute = attribute
    @type = type
    @options = options
  end

  attr_reader :base, :attribute, :type, :options

  # Full message of the error.
  #
  # === Key differences to Rails vanilla errors
  #
  # ==== 1. Flexible positioning of attribute name interpolation
  #
  # In Rails, errors' full messages are always prefixed with attribute name,
  # and if prefix is not wanted, developer often adds error to the `base' attribute instead.
  # This can be unreasonable in different languages or special business requirements.
  #
  # AdequateErrors leaves the attribute placement to the developer.
  # For each error message in the locale file, the %{attribute} indicates placement of the attribute.
  # The same error can have prefix in English, and be prefix-less in Russian.
  # If no prefix is needed, one should update the locale file accordingly,
  #
  # ==== 2. Message evaluated lazily
  #
  # In Rails, error message is evaluated during the `add` call.
  # AdequateErrors evaluates message lazily at `message` call instead,
  # so one can change message locale after model has been validated.
  #
  # === Order of I18n lookup:
  #
  # Error messages are first looked up in <tt>activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>,
  # if it's not there, it's looked up in <tt>activemodel.adequate_errors.models.MODEL.MESSAGE</tt> and if
  # that is not there also, it returns the translation of the default message
  # (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model
  # name, translated attribute name and the value are available for
  # interpolation.
  #
  # When using inheritance 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:
  #
  # * <tt>activemodel.adequate_errors.models.admin.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.admin.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.blank</tt>
  # * any default you provided through the +options+ hash (in the <tt>activemodel.adequate_errors</tt> scope)
  # * <tt>activemodel.adequate_errors.messages.blank</tt>
  # * <tt>adequate_errors.attributes.title.blank</tt>
  # * <tt>adequate_errors.messages.blank</tt>
  def message
    if @options[:message].is_a?(Symbol)
      type = @options.delete(:message)
    else
      type = @type
    end

    if @base.class.respond_to?(:i18n_scope)
      i18n_scope = @base.class.i18n_scope.to_s
      defaults = @base.class.lookup_ancestors.flat_map do |klass|
        [ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
          :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ]
      end
      defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}"
    else
      defaults = []
    end

    defaults << :"adequate_errors.attributes.#{attribute}.#{type}"
    defaults << :"adequate_errors.messages.#{type}"

    key = defaults.shift
    defaults = @options.delete(:message) if @options[:message]
    value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)

    i18n_options = {
      default: defaults,
      model: @base.model_name.human,
      attribute: humanized_attribute,
      value: value,
      object: @base,
      exception_handler: ->(exception, locale, key, option) {
        rails_errors = @base.errors
        rails_errors.full_message(@attribute, rails_errors.generate_message(@attribute, @type, @options))
      }
    }.merge!(@options)

    I18n.translate(key, i18n_options)
  end

  # @param (see Errors#where)
  # @return [Boolean] whether error matches the params
  def match?(params)
    if params.key?(:attribute) && @attribute != params[:attribute]
      return false
    end

    if params.key?(:type) && @type != params[:type]
      return false
    end

    (params.keys - [:attribute, :type]).each do |key|
      if @options[key] != params[key]
        return false
      end
    end

    true
  end

  private

  def humanized_attribute
    default = @attribute.to_s.tr(".", "_").humanize
    @base.class.human_attribute_name(@attribute, default: default)
  end

end

#baseActiveModel::Base (readonly)

Returns the object which the error belongs to.

Returns:

  • (ActiveModel::Base)

    the object which the error belongs to



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/adequate_errors/error.rb', line 11

class Error
  def initialize(base, attribute, type, options = {})
    @base = base
    @attribute = attribute
    @type = type
    @options = options
  end

  attr_reader :base, :attribute, :type, :options

  # Full message of the error.
  #
  # === Key differences to Rails vanilla errors
  #
  # ==== 1. Flexible positioning of attribute name interpolation
  #
  # In Rails, errors' full messages are always prefixed with attribute name,
  # and if prefix is not wanted, developer often adds error to the `base' attribute instead.
  # This can be unreasonable in different languages or special business requirements.
  #
  # AdequateErrors leaves the attribute placement to the developer.
  # For each error message in the locale file, the %{attribute} indicates placement of the attribute.
  # The same error can have prefix in English, and be prefix-less in Russian.
  # If no prefix is needed, one should update the locale file accordingly,
  #
  # ==== 2. Message evaluated lazily
  #
  # In Rails, error message is evaluated during the `add` call.
  # AdequateErrors evaluates message lazily at `message` call instead,
  # so one can change message locale after model has been validated.
  #
  # === Order of I18n lookup:
  #
  # Error messages are first looked up in <tt>activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>,
  # if it's not there, it's looked up in <tt>activemodel.adequate_errors.models.MODEL.MESSAGE</tt> and if
  # that is not there also, it returns the translation of the default message
  # (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model
  # name, translated attribute name and the value are available for
  # interpolation.
  #
  # When using inheritance 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:
  #
  # * <tt>activemodel.adequate_errors.models.admin.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.admin.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.blank</tt>
  # * any default you provided through the +options+ hash (in the <tt>activemodel.adequate_errors</tt> scope)
  # * <tt>activemodel.adequate_errors.messages.blank</tt>
  # * <tt>adequate_errors.attributes.title.blank</tt>
  # * <tt>adequate_errors.messages.blank</tt>
  def message
    if @options[:message].is_a?(Symbol)
      type = @options.delete(:message)
    else
      type = @type
    end

    if @base.class.respond_to?(:i18n_scope)
      i18n_scope = @base.class.i18n_scope.to_s
      defaults = @base.class.lookup_ancestors.flat_map do |klass|
        [ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
          :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ]
      end
      defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}"
    else
      defaults = []
    end

    defaults << :"adequate_errors.attributes.#{attribute}.#{type}"
    defaults << :"adequate_errors.messages.#{type}"

    key = defaults.shift
    defaults = @options.delete(:message) if @options[:message]
    value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)

    i18n_options = {
      default: defaults,
      model: @base.model_name.human,
      attribute: humanized_attribute,
      value: value,
      object: @base,
      exception_handler: ->(exception, locale, key, option) {
        rails_errors = @base.errors
        rails_errors.full_message(@attribute, rails_errors.generate_message(@attribute, @type, @options))
      }
    }.merge!(@options)

    I18n.translate(key, i18n_options)
  end

  # @param (see Errors#where)
  # @return [Boolean] whether error matches the params
  def match?(params)
    if params.key?(:attribute) && @attribute != params[:attribute]
      return false
    end

    if params.key?(:type) && @type != params[:type]
      return false
    end

    (params.keys - [:attribute, :type]).each do |key|
      if @options[key] != params[key]
        return false
      end
    end

    true
  end

  private

  def humanized_attribute
    default = @attribute.to_s.tr(".", "_").humanize
    @base.class.human_attribute_name(@attribute, default: default)
  end

end

#optionsHash (readonly)

Returns additional options.

Returns:

  • (Hash)

    additional options



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/adequate_errors/error.rb', line 11

class Error
  def initialize(base, attribute, type, options = {})
    @base = base
    @attribute = attribute
    @type = type
    @options = options
  end

  attr_reader :base, :attribute, :type, :options

  # Full message of the error.
  #
  # === Key differences to Rails vanilla errors
  #
  # ==== 1. Flexible positioning of attribute name interpolation
  #
  # In Rails, errors' full messages are always prefixed with attribute name,
  # and if prefix is not wanted, developer often adds error to the `base' attribute instead.
  # This can be unreasonable in different languages or special business requirements.
  #
  # AdequateErrors leaves the attribute placement to the developer.
  # For each error message in the locale file, the %{attribute} indicates placement of the attribute.
  # The same error can have prefix in English, and be prefix-less in Russian.
  # If no prefix is needed, one should update the locale file accordingly,
  #
  # ==== 2. Message evaluated lazily
  #
  # In Rails, error message is evaluated during the `add` call.
  # AdequateErrors evaluates message lazily at `message` call instead,
  # so one can change message locale after model has been validated.
  #
  # === Order of I18n lookup:
  #
  # Error messages are first looked up in <tt>activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>,
  # if it's not there, it's looked up in <tt>activemodel.adequate_errors.models.MODEL.MESSAGE</tt> and if
  # that is not there also, it returns the translation of the default message
  # (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model
  # name, translated attribute name and the value are available for
  # interpolation.
  #
  # When using inheritance 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:
  #
  # * <tt>activemodel.adequate_errors.models.admin.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.admin.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.blank</tt>
  # * any default you provided through the +options+ hash (in the <tt>activemodel.adequate_errors</tt> scope)
  # * <tt>activemodel.adequate_errors.messages.blank</tt>
  # * <tt>adequate_errors.attributes.title.blank</tt>
  # * <tt>adequate_errors.messages.blank</tt>
  def message
    if @options[:message].is_a?(Symbol)
      type = @options.delete(:message)
    else
      type = @type
    end

    if @base.class.respond_to?(:i18n_scope)
      i18n_scope = @base.class.i18n_scope.to_s
      defaults = @base.class.lookup_ancestors.flat_map do |klass|
        [ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
          :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ]
      end
      defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}"
    else
      defaults = []
    end

    defaults << :"adequate_errors.attributes.#{attribute}.#{type}"
    defaults << :"adequate_errors.messages.#{type}"

    key = defaults.shift
    defaults = @options.delete(:message) if @options[:message]
    value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)

    i18n_options = {
      default: defaults,
      model: @base.model_name.human,
      attribute: humanized_attribute,
      value: value,
      object: @base,
      exception_handler: ->(exception, locale, key, option) {
        rails_errors = @base.errors
        rails_errors.full_message(@attribute, rails_errors.generate_message(@attribute, @type, @options))
      }
    }.merge!(@options)

    I18n.translate(key, i18n_options)
  end

  # @param (see Errors#where)
  # @return [Boolean] whether error matches the params
  def match?(params)
    if params.key?(:attribute) && @attribute != params[:attribute]
      return false
    end

    if params.key?(:type) && @type != params[:type]
      return false
    end

    (params.keys - [:attribute, :type]).each do |key|
      if @options[key] != params[key]
        return false
      end
    end

    true
  end

  private

  def humanized_attribute
    default = @attribute.to_s.tr(".", "_").humanize
    @base.class.human_attribute_name(@attribute, default: default)
  end

end

#typeSymbol (readonly)

Returns error’s type.

Returns:

  • (Symbol)

    error’s type



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/adequate_errors/error.rb', line 11

class Error
  def initialize(base, attribute, type, options = {})
    @base = base
    @attribute = attribute
    @type = type
    @options = options
  end

  attr_reader :base, :attribute, :type, :options

  # Full message of the error.
  #
  # === Key differences to Rails vanilla errors
  #
  # ==== 1. Flexible positioning of attribute name interpolation
  #
  # In Rails, errors' full messages are always prefixed with attribute name,
  # and if prefix is not wanted, developer often adds error to the `base' attribute instead.
  # This can be unreasonable in different languages or special business requirements.
  #
  # AdequateErrors leaves the attribute placement to the developer.
  # For each error message in the locale file, the %{attribute} indicates placement of the attribute.
  # The same error can have prefix in English, and be prefix-less in Russian.
  # If no prefix is needed, one should update the locale file accordingly,
  #
  # ==== 2. Message evaluated lazily
  #
  # In Rails, error message is evaluated during the `add` call.
  # AdequateErrors evaluates message lazily at `message` call instead,
  # so one can change message locale after model has been validated.
  #
  # === Order of I18n lookup:
  #
  # Error messages are first looked up in <tt>activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>,
  # if it's not there, it's looked up in <tt>activemodel.adequate_errors.models.MODEL.MESSAGE</tt> and if
  # that is not there also, it returns the translation of the default message
  # (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model
  # name, translated attribute name and the value are available for
  # interpolation.
  #
  # When using inheritance 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:
  #
  # * <tt>activemodel.adequate_errors.models.admin.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.admin.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.attributes.title.blank</tt>
  # * <tt>activemodel.adequate_errors.models.user.blank</tt>
  # * any default you provided through the +options+ hash (in the <tt>activemodel.adequate_errors</tt> scope)
  # * <tt>activemodel.adequate_errors.messages.blank</tt>
  # * <tt>adequate_errors.attributes.title.blank</tt>
  # * <tt>adequate_errors.messages.blank</tt>
  def message
    if @options[:message].is_a?(Symbol)
      type = @options.delete(:message)
    else
      type = @type
    end

    if @base.class.respond_to?(:i18n_scope)
      i18n_scope = @base.class.i18n_scope.to_s
      defaults = @base.class.lookup_ancestors.flat_map do |klass|
        [ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
          :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ]
      end
      defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}"
    else
      defaults = []
    end

    defaults << :"adequate_errors.attributes.#{attribute}.#{type}"
    defaults << :"adequate_errors.messages.#{type}"

    key = defaults.shift
    defaults = @options.delete(:message) if @options[:message]
    value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)

    i18n_options = {
      default: defaults,
      model: @base.model_name.human,
      attribute: humanized_attribute,
      value: value,
      object: @base,
      exception_handler: ->(exception, locale, key, option) {
        rails_errors = @base.errors
        rails_errors.full_message(@attribute, rails_errors.generate_message(@attribute, @type, @options))
      }
    }.merge!(@options)

    I18n.translate(key, i18n_options)
  end

  # @param (see Errors#where)
  # @return [Boolean] whether error matches the params
  def match?(params)
    if params.key?(:attribute) && @attribute != params[:attribute]
      return false
    end

    if params.key?(:type) && @type != params[:type]
      return false
    end

    (params.keys - [:attribute, :type]).each do |key|
      if @options[key] != params[key]
        return false
      end
    end

    true
  end

  private

  def humanized_attribute
    default = @attribute.to_s.tr(".", "_").humanize
    @base.class.human_attribute_name(@attribute, default: default)
  end

end

Instance Method Details

#match?(params) ⇒ Boolean

Returns whether error matches the params.

Parameters:

  • params (Hash)

    filter condition The most common keys are :attribute and :type, but other custom keys given during AdequateErrors::Errors#add can also be used. If params is empty, all errors are returned.

Returns:

  • (Boolean)

    whether error matches the params



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/adequate_errors/error.rb', line 107

def match?(params)
  if params.key?(:attribute) && @attribute != params[:attribute]
    return false
  end

  if params.key?(:type) && @type != params[:type]
    return false
  end

  (params.keys - [:attribute, :type]).each do |key|
    if @options[key] != params[key]
      return false
    end
  end

  true
end

#messageObject

Full message of the error.

Key differences to Rails vanilla errors

1. Flexible positioning of attribute name interpolation

In Rails, errors’ full messages are always prefixed with attribute name, and if prefix is not wanted, developer often adds error to the ‘base’ attribute instead. This can be unreasonable in different languages or special business requirements.

AdequateErrors leaves the attribute placement to the developer. For each error message in the locale file, the %#attribute indicates placement of the attribute. The same error can have prefix in English, and be prefix-less in Russian. If no prefix is needed, one should update the locale file accordingly,

2. Message evaluated lazily

In Rails, error message is evaluated during the ‘add` call. AdequateErrors evaluates message lazily at `message` call instead, so one can change message locale after model has been validated.

Order of I18n lookup:

Error messages are first looked up in activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE, if it’s not there, it’s looked up in activemodel.adequate_errors.models.MODEL.MESSAGE and if that is not there also, it returns the translation of the default message (e.g. activemodel.errors.messages.MESSAGE). The translated model name, translated attribute name and the value are available for interpolation.

When using inheritance in your models, it will check all the inherited models too, but only if the model itself hasn’t been found. Say you have class Admin < User; end and you wanted the translation for the :blank error message for the title attribute, it looks for these translations:

  • activemodel.adequate_errors.models.admin.attributes.title.blank

  • activemodel.adequate_errors.models.admin.blank

  • activemodel.adequate_errors.models.user.attributes.title.blank

  • activemodel.adequate_errors.models.user.blank

  • any default you provided through the options hash (in the activemodel.adequate_errors scope)

  • activemodel.adequate_errors.messages.blank

  • adequate_errors.attributes.title.blank

  • adequate_errors.messages.blank



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/adequate_errors/error.rb', line 65

def message
  if @options[:message].is_a?(Symbol)
    type = @options.delete(:message)
  else
    type = @type
  end

  if @base.class.respond_to?(:i18n_scope)
    i18n_scope = @base.class.i18n_scope.to_s
    defaults = @base.class.lookup_ancestors.flat_map do |klass|
      [ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
        :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ]
    end
    defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}"
  else
    defaults = []
  end

  defaults << :"adequate_errors.attributes.#{attribute}.#{type}"
  defaults << :"adequate_errors.messages.#{type}"

  key = defaults.shift
  defaults = @options.delete(:message) if @options[:message]
  value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)

  i18n_options = {
    default: defaults,
    model: @base.model_name.human,
    attribute: humanized_attribute,
    value: value,
    object: @base,
    exception_handler: ->(exception, locale, key, option) {
      rails_errors = @base.errors
      rails_errors.full_message(@attribute, rails_errors.generate_message(@attribute, @type, @options))
    }
  }.merge!(@options)

  I18n.translate(key, i18n_options)
end