File: validations.rb

package info (click to toggle)
libgettext-activerecord-ruby 2.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 608 kB
  • ctags: 285
  • sloc: ruby: 2,895; makefile: 13
file content (190 lines) | stat: -rw-r--r-- 7,314 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
=begin
  lib/gettext_activerecord/validations.rb - GetText for ActiveRecord

  Copyright (C) 2006-2009  Masao Mutoh

  You may redistribute it and/or modify it under the same
  license terms as Ruby or LGPL.
=end

module ActiveRecord #:nodoc:
  class RecordInvalid < ActiveRecordError #:nodoc:
    attr_reader :record
    include GetText
    bindtextdomain "gettext_activerecord"

    def initialize(record)
      @record = record
      super(_("Validation failed: %{error_messages}") % 
            {:error_messages => @record.errors.full_messages.join(", ")})
    end
  end

  module Validations # :nodoc:
    class << self
      def real_included(base)
        base.extend ClassMethods
        base.class_eval{
          include GetText
          def gettext(str)  #:nodoc:
            _(str)
          end
          class << self
            def human_attribute_name_with_gettext_activerecord(attribute_key_name) #:nodoc:
              s_("#{self.to_s_with_gettext}|#{attribute_key_name.humanize}")
            end
            alias_method_chain :human_attribute_name, :gettext_activerecord

            def human_attribute_table_name_for_error(table_name) #:nodoc:
              _(table_name.gsub(/_/, " "))
            end
          end
        }
      end
    end

    if respond_to? :included
      class << self
        def included_with_gettext_activerecord(base) # :nodoc:
          unless base <= ActiveRecord::Base
            included_without_gettext_activerecord(base)
          end
          real_included(base)
        end
        alias_method_chain :included, :gettext_activerecord
      end
    else
      class << self
        # Since rails-1.2.0.
        def append_features_with_gettext_activerecord(base) # :nodoc:
          unless base <= ActiveRecord::Base
            append_features_without_gettext_activerecord(base)
          end
          real_included(base)
        end
        alias_method_chain :append_features, :gettext_activerecord
      end
    end
  end

  # activerecord-1.14.3/lib/active_record/validations.rb
  class Errors #:nodoc:
    include GetText

    textdomain "gettext_activerecord"

    class << self
      include GetText

      def default_error_messages_with_gettext_activerecord
        @@default_error_messages || {}
      end
      alias_method_chain :default_error_messages, :gettext_activerecord

      # To use other backends, gettext_activerecord doesn't use backend architecture.
      # You can use GetText with other backends.
      @@default_error_messages = {
          :inclusion => N_("%{attribute} is not included in the list"),
          :exclusion => N_("%{attribute} is reserved"),
          :invalid => N_("%{attribute} is invalid"),
          :confirmation => N_("%{attribute} doesn't match confirmation"),
          :accepted  => N_("%{attribute} must be accepted"),
          :empty => N_("%{attribute} can't be empty"),
          :blank => N_("%{attribute} can't be blank"),
          :too_long => N_("%{attribute} is too long (maximum is %{count} characters)"),  
          :too_short => N_("%{attribute} is too short (minimum is %{count} characters)"), 
          :wrong_length => N_("%{attribute} is the wrong length (should be %{count} characters)"),
          :taken => N_("%{attribute} has already been taken"),
          :not_a_number => N_("%{attribute} is not a number"),
          :greater_than => N_("%{attribute} must be greater than %{count}"),
          :greater_than_or_equal_to => N_("%{attribute} must be greater than or equal to %{count}"),
          :equal_to => N_("%{attribute} must be equal to %{count}"),
          :less_than => N_("%{attribute} must be less than %{count}"),
          :less_than_or_equal_to => N_("%{attribute} must be less than or equal to %{count}"),
          :odd => N_("%{attribute} must be odd"),
          :even => N_("%{attribute} must be even")
      }
    end

    def each_with_gettext_activerecord #:nodoc:
      @errors.each_key { |attr| @errors[attr].each { |msg| yield attr, localize_error_message(attr, msg, false) } }
    end
    alias_method_chain :each, :gettext_activerecord

    # Returns error messages.
    # * Returns nil, if no errors are associated with the specified attribute.
    # * Returns the error message, if one error is associated with the specified attribute.
    # * Returns an array of error messages, if more than one error is associated with the specified attribute.
    # And for GetText,
    # * If the error messages include %{fn}, it returns formatted text such as "foo %{fn}" => "foo Field"
    # * else, the error messages are prepended the field name such as "foo" => "foo" (Same as default behavior).
    # Note that this behaviour is different from full_messages.
    def on_with_gettext_activerecord(attribute)
      # e.g.) foo field: "%{fn} foo" => "Foo foo", "foo" => "foo". 
      errors = localize_error_messages(false)[attribute.to_s]
      return nil if errors.nil?
      errors.size == 1 ? errors.first : errors
    end
    alias_method_chain :on, :gettext_activerecord
    alias :[] :on

    # Returns all the full error messages in an array.
    # * If the error messages include %{fn}, it returns formatted text such as "foo %{fn}" => "foo Field"
    # * else, the error messages are prepended the field name such as "foo" => "Field foo" (Same as default behavior).
    # As L10n, first one is recommanded because the order of subject,verb and others are not same in languages.
    def full_messages_with_gettext_activerecord
      full_messages = []
      errors = localize_error_messages
      errors.each_key do |attr|
        errors[attr].each do |msg|
   	  next if msg.nil?
          full_messages << msg
        end
      end
      full_messages
    end
    alias_method_chain :full_messages, :gettext_activerecord 

    private
    def localize_error_message(attr, object, append_field) # :nodoc:
     obj =  object.respond_to?(:message) ? object.message : object

      msgid, count, value = obj, 0, ""
      if obj.kind_of? Hash
        msgid = obj[:default].select{|v| v.is_a? String}[0]
        unless msgid
          symbol = obj[:default][0].to_s.split(".").last.to_sym
          msgid = @@default_error_messages[symbol]
        end
        #attr, count, value = obj[:attribute], obj[:count], obj[:value]
        count, value = obj[:count], obj[:value]
        attr = obj[:attribute] if obj[:attribute]
      end
      msgstr = @base.gettext(msgid)
      msgstr = _(msgid) if msgstr == msgid 
      msgstr = msgstr.gsub("%{fn}", "%{attribute}").gsub("%d", "%{count}").gsub("%{val}", "%{value}")  # for backward compatibility.
      attrname = @base.class.human_attribute_name(attr)
      if attr == "base"
        full_message = msgstr
      elsif append_field
        full_message = attrname + " " + msgstr
      else
        full_message = msgstr
      end
      full_message % {:count => count, :value => value, :attribute => attrname}
    end

    def localize_error_messages(append_field = true) # :nodoc:
      # e.g.) foo field: "%{fn} foo" => "Foo foo", "foo" => "Foo foo". 
      errors = {}
      each_without_gettext_activerecord {|attr, msg|
        next if msg.nil?
        errors[attr] ||= []
        errors[attr] << localize_error_message(attr, msg, append_field)
      }
      errors
    end

  end
end