activemodel 3.2.22.5 → 4.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +85 -64
 - data/MIT-LICENSE +1 -1
 - data/README.rdoc +61 -24
 - data/lib/active_model.rb +21 -11
 - data/lib/active_model/attribute_methods.rb +150 -125
 - data/lib/active_model/callbacks.rb +49 -34
 - data/lib/active_model/conversion.rb +39 -19
 - data/lib/active_model/deprecated_mass_assignment_security.rb +21 -0
 - data/lib/active_model/dirty.rb +48 -32
 - data/lib/active_model/errors.rb +176 -88
 - data/lib/active_model/forbidden_attributes_protection.rb +27 -0
 - data/lib/active_model/lint.rb +42 -55
 - data/lib/active_model/locale/en.yml +3 -1
 - data/lib/active_model/model.rb +97 -0
 - data/lib/active_model/naming.rb +191 -51
 - data/lib/active_model/railtie.rb +11 -1
 - data/lib/active_model/secure_password.rb +55 -25
 - data/lib/active_model/serialization.rb +51 -27
 - data/lib/active_model/serializers/json.rb +83 -46
 - data/lib/active_model/serializers/xml.rb +46 -12
 - data/lib/active_model/test_case.rb +0 -12
 - data/lib/active_model/translation.rb +9 -10
 - data/lib/active_model/validations.rb +154 -52
 - data/lib/active_model/validations/absence.rb +31 -0
 - data/lib/active_model/validations/acceptance.rb +10 -22
 - data/lib/active_model/validations/callbacks.rb +78 -25
 - data/lib/active_model/validations/clusivity.rb +41 -0
 - data/lib/active_model/validations/confirmation.rb +13 -23
 - data/lib/active_model/validations/exclusion.rb +26 -55
 - data/lib/active_model/validations/format.rb +44 -34
 - data/lib/active_model/validations/inclusion.rb +22 -52
 - data/lib/active_model/validations/length.rb +48 -49
 - data/lib/active_model/validations/numericality.rb +30 -32
 - data/lib/active_model/validations/presence.rb +12 -22
 - data/lib/active_model/validations/validates.rb +68 -36
 - data/lib/active_model/validations/with.rb +28 -23
 - data/lib/active_model/validator.rb +22 -22
 - data/lib/active_model/version.rb +4 -4
 - metadata +23 -24
 - data/lib/active_model/mass_assignment_security.rb +0 -237
 - data/lib/active_model/mass_assignment_security/permission_set.rb +0 -40
 - data/lib/active_model/mass_assignment_security/sanitizer.rb +0 -59
 - data/lib/active_model/observer_array.rb +0 -147
 - data/lib/active_model/observing.rb +0 -252
 
    
        data/lib/active_model/errors.rb
    CHANGED
    
    | 
         @@ -1,16 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # -*- coding: utf-8 -*-
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require 'active_support/core_ext/array/wrap'
         
     | 
| 
       4 
3 
     | 
    
         
             
            require 'active_support/core_ext/array/conversions'
         
     | 
| 
       5 
4 
     | 
    
         
             
            require 'active_support/core_ext/string/inflections'
         
     | 
| 
       6 
     | 
    
         
            -
            require 'active_support/core_ext/object/blank'
         
     | 
| 
       7 
     | 
    
         
            -
            require 'active_support/core_ext/hash/reverse_merge'
         
     | 
| 
       8 
     | 
    
         
            -
            require 'active_support/ordered_hash'
         
     | 
| 
       9 
5 
     | 
    
         | 
| 
       10 
6 
     | 
    
         
             
            module ActiveModel
         
     | 
| 
       11 
     | 
    
         
            -
              # == Active Model Errors
         
     | 
| 
      
 7 
     | 
    
         
            +
              # == Active \Model \Errors
         
     | 
| 
       12 
8 
     | 
    
         
             
              #
         
     | 
| 
       13 
     | 
    
         
            -
              # Provides a modified + 
     | 
| 
      
 9 
     | 
    
         
            +
              # Provides a modified +Hash+ that you can include in your object
         
     | 
| 
       14 
10 
     | 
    
         
             
              # for handling error messages and interacting with Action Pack helpers.
         
     | 
| 
       15 
11 
     | 
    
         
             
              #
         
     | 
| 
       16 
12 
     | 
    
         
             
              # A minimal implementation could be:
         
     | 
| 
         @@ -57,8 +53,8 @@ module ActiveModel 
     | 
|
| 
       57 
53 
     | 
    
         
             
              # The above allows you to do:
         
     | 
| 
       58 
54 
     | 
    
         
             
              #
         
     | 
| 
       59 
55 
     | 
    
         
             
              #   p = Person.new
         
     | 
| 
       60 
     | 
    
         
            -
              #    
     | 
| 
       61 
     | 
    
         
            -
              #    
     | 
| 
      
 56 
     | 
    
         
            +
              #   person.validate!            # => ["can not be nil"]
         
     | 
| 
      
 57 
     | 
    
         
            +
              #   person.errors.full_messages # => ["name can not be nil"]
         
     | 
| 
       62 
58 
     | 
    
         
             
              #   # etc..
         
     | 
| 
       63 
59 
     | 
    
         
             
              class Errors
         
     | 
| 
       64 
60 
     | 
    
         
             
                include Enumerable
         
     | 
| 
         @@ -76,44 +72,58 @@ module ActiveModel 
     | 
|
| 
       76 
72 
     | 
    
         
             
                #   end
         
     | 
| 
       77 
73 
     | 
    
         
             
                def initialize(base)
         
     | 
| 
       78 
74 
     | 
    
         
             
                  @base     = base
         
     | 
| 
       79 
     | 
    
         
            -
                  @messages =  
     | 
| 
      
 75 
     | 
    
         
            +
                  @messages = {}
         
     | 
| 
       80 
76 
     | 
    
         
             
                end
         
     | 
| 
       81 
77 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                def initialize_dup(other)
         
     | 
| 
      
 78 
     | 
    
         
            +
                def initialize_dup(other) # :nodoc:
         
     | 
| 
       83 
79 
     | 
    
         
             
                  @messages = other.messages.dup
         
     | 
| 
      
 80 
     | 
    
         
            +
                  super
         
     | 
| 
       84 
81 
     | 
    
         
             
                end
         
     | 
| 
       85 
82 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                #  
     | 
| 
       87 
     | 
    
         
            -
                 
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
                    copy
         
     | 
| 
       92 
     | 
    
         
            -
                  end
         
     | 
| 
       93 
     | 
    
         
            -
                end
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                # Clear the messages
         
     | 
| 
      
 83 
     | 
    
         
            +
                # Clear the error messages.
         
     | 
| 
      
 84 
     | 
    
         
            +
                #
         
     | 
| 
      
 85 
     | 
    
         
            +
                #   person.errors.full_messages # => ["name can not be nil"]
         
     | 
| 
      
 86 
     | 
    
         
            +
                #   person.errors.clear
         
     | 
| 
      
 87 
     | 
    
         
            +
                #   person.errors.full_messages # => []
         
     | 
| 
       96 
88 
     | 
    
         
             
                def clear
         
     | 
| 
       97 
89 
     | 
    
         
             
                  messages.clear
         
     | 
| 
       98 
90 
     | 
    
         
             
                end
         
     | 
| 
       99 
91 
     | 
    
         | 
| 
       100 
     | 
    
         
            -
                #  
     | 
| 
       101 
     | 
    
         
            -
                 
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
      
 92 
     | 
    
         
            +
                # Returns +true+ if the error messages include an error for the given key
         
     | 
| 
      
 93 
     | 
    
         
            +
                # +attribute+, +false+ otherwise.
         
     | 
| 
      
 94 
     | 
    
         
            +
                #
         
     | 
| 
      
 95 
     | 
    
         
            +
                #   person.errors.messages        # => {:name=>["can not be nil"]}
         
     | 
| 
      
 96 
     | 
    
         
            +
                #   person.errors.include?(:name) # => true
         
     | 
| 
      
 97 
     | 
    
         
            +
                #   person.errors.include?(:age)  # => false
         
     | 
| 
      
 98 
     | 
    
         
            +
                def include?(attribute)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  (v = messages[attribute]) && v.any?
         
     | 
| 
       103 
100 
     | 
    
         
             
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
                # aliases include?
         
     | 
| 
       104 
102 
     | 
    
         
             
                alias :has_key? :include?
         
     | 
| 
       105 
103 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
                # Get messages for +key 
     | 
| 
      
 104 
     | 
    
         
            +
                # Get messages for +key+.
         
     | 
| 
      
 105 
     | 
    
         
            +
                #
         
     | 
| 
      
 106 
     | 
    
         
            +
                #   person.errors.messages   # => {:name=>["can not be nil"]}
         
     | 
| 
      
 107 
     | 
    
         
            +
                #   person.errors.get(:name) # => ["can not be nil"]
         
     | 
| 
      
 108 
     | 
    
         
            +
                #   person.errors.get(:age)  # => nil
         
     | 
| 
       107 
109 
     | 
    
         
             
                def get(key)
         
     | 
| 
       108 
110 
     | 
    
         
             
                  messages[key]
         
     | 
| 
       109 
111 
     | 
    
         
             
                end
         
     | 
| 
       110 
112 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
                # Set messages for +key+ to +value 
     | 
| 
      
 113 
     | 
    
         
            +
                # Set messages for +key+ to +value+.
         
     | 
| 
      
 114 
     | 
    
         
            +
                #
         
     | 
| 
      
 115 
     | 
    
         
            +
                #   person.errors.get(:name) # => ["can not be nil"]
         
     | 
| 
      
 116 
     | 
    
         
            +
                #   person.errors.set(:name, ["can't be nil"])
         
     | 
| 
      
 117 
     | 
    
         
            +
                #   person.errors.get(:name) # => ["can't be nil"]
         
     | 
| 
       112 
118 
     | 
    
         
             
                def set(key, value)
         
     | 
| 
       113 
119 
     | 
    
         
             
                  messages[key] = value
         
     | 
| 
       114 
120 
     | 
    
         
             
                end
         
     | 
| 
       115 
121 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
                # Delete messages for +key 
     | 
| 
      
 122 
     | 
    
         
            +
                # Delete messages for +key+. Returns the deleted messages.
         
     | 
| 
      
 123 
     | 
    
         
            +
                #
         
     | 
| 
      
 124 
     | 
    
         
            +
                #   person.errors.get(:name)    # => ["can not be nil"]
         
     | 
| 
      
 125 
     | 
    
         
            +
                #   person.errors.delete(:name) # => ["can not be nil"]
         
     | 
| 
      
 126 
     | 
    
         
            +
                #   person.errors.get(:name)    # => nil
         
     | 
| 
       117 
127 
     | 
    
         
             
                def delete(key)
         
     | 
| 
       118 
128 
     | 
    
         
             
                  messages.delete(key)
         
     | 
| 
       119 
129 
     | 
    
         
             
                end
         
     | 
| 
         @@ -121,16 +131,16 @@ module ActiveModel 
     | 
|
| 
       121 
131 
     | 
    
         
             
                # When passed a symbol or a name of a method, returns an array of errors
         
     | 
| 
       122 
132 
     | 
    
         
             
                # for the method.
         
     | 
| 
       123 
133 
     | 
    
         
             
                #
         
     | 
| 
       124 
     | 
    
         
            -
                #    
     | 
| 
       125 
     | 
    
         
            -
                #    
     | 
| 
      
 134 
     | 
    
         
            +
                #   person.errors[:name]  # => ["can not be nil"]
         
     | 
| 
      
 135 
     | 
    
         
            +
                #   person.errors['name'] # => ["can not be nil"]
         
     | 
| 
       126 
136 
     | 
    
         
             
                def [](attribute)
         
     | 
| 
       127 
137 
     | 
    
         
             
                  get(attribute.to_sym) || set(attribute.to_sym, [])
         
     | 
| 
       128 
138 
     | 
    
         
             
                end
         
     | 
| 
       129 
139 
     | 
    
         | 
| 
       130 
140 
     | 
    
         
             
                # Adds to the supplied attribute the supplied error message.
         
     | 
| 
       131 
141 
     | 
    
         
             
                #
         
     | 
| 
       132 
     | 
    
         
            -
                #    
     | 
| 
       133 
     | 
    
         
            -
                #    
     | 
| 
      
 142 
     | 
    
         
            +
                #   person.errors[:name] = "must be set"
         
     | 
| 
      
 143 
     | 
    
         
            +
                #   person.errors[:name] # => ['must be set']
         
     | 
| 
       134 
144 
     | 
    
         
             
                def []=(attribute, error)
         
     | 
| 
       135 
145 
     | 
    
         
             
                  self[attribute] << error
         
     | 
| 
       136 
146 
     | 
    
         
             
                end
         
     | 
| 
         @@ -139,13 +149,13 @@ module ActiveModel 
     | 
|
| 
       139 
149 
     | 
    
         
             
                # Yields the attribute and the error for that attribute. If the attribute
         
     | 
| 
       140 
150 
     | 
    
         
             
                # has more than one error message, yields once for each error message.
         
     | 
| 
       141 
151 
     | 
    
         
             
                #
         
     | 
| 
       142 
     | 
    
         
            -
                #    
     | 
| 
       143 
     | 
    
         
            -
                #    
     | 
| 
      
 152 
     | 
    
         
            +
                #   person.errors.add(:name, "can't be blank")
         
     | 
| 
      
 153 
     | 
    
         
            +
                #   person.errors.each do |attribute, error|
         
     | 
| 
       144 
154 
     | 
    
         
             
                #     # Will yield :name and "can't be blank"
         
     | 
| 
       145 
155 
     | 
    
         
             
                #   end
         
     | 
| 
       146 
156 
     | 
    
         
             
                #
         
     | 
| 
       147 
     | 
    
         
            -
                #    
     | 
| 
       148 
     | 
    
         
            -
                #    
     | 
| 
      
 157 
     | 
    
         
            +
                #   person.errors.add(:name, "must be specified")
         
     | 
| 
      
 158 
     | 
    
         
            +
                #   person.errors.each do |attribute, error|
         
     | 
| 
       149 
159 
     | 
    
         
             
                #     # Will yield :name and "can't be blank"
         
     | 
| 
       150 
160 
     | 
    
         
             
                #     # then yield :name and "must be specified"
         
     | 
| 
       151 
161 
     | 
    
         
             
                #   end
         
     | 
| 
         @@ -157,54 +167,65 @@ module ActiveModel 
     | 
|
| 
       157 
167 
     | 
    
         | 
| 
       158 
168 
     | 
    
         
             
                # Returns the number of error messages.
         
     | 
| 
       159 
169 
     | 
    
         
             
                #
         
     | 
| 
       160 
     | 
    
         
            -
                #    
     | 
| 
       161 
     | 
    
         
            -
                #    
     | 
| 
       162 
     | 
    
         
            -
                #    
     | 
| 
       163 
     | 
    
         
            -
                #    
     | 
| 
      
 170 
     | 
    
         
            +
                #   person.errors.add(:name, "can't be blank")
         
     | 
| 
      
 171 
     | 
    
         
            +
                #   person.errors.size # => 1
         
     | 
| 
      
 172 
     | 
    
         
            +
                #   person.errors.add(:name, "must be specified")
         
     | 
| 
      
 173 
     | 
    
         
            +
                #   person.errors.size # => 2
         
     | 
| 
       164 
174 
     | 
    
         
             
                def size
         
     | 
| 
       165 
175 
     | 
    
         
             
                  values.flatten.size
         
     | 
| 
       166 
176 
     | 
    
         
             
                end
         
     | 
| 
       167 
177 
     | 
    
         | 
| 
       168 
     | 
    
         
            -
                # Returns all message values
         
     | 
| 
      
 178 
     | 
    
         
            +
                # Returns all message values.
         
     | 
| 
      
 179 
     | 
    
         
            +
                #
         
     | 
| 
      
 180 
     | 
    
         
            +
                #   person.errors.messages # => {:name=>["can not be nil", "must be specified"]}
         
     | 
| 
      
 181 
     | 
    
         
            +
                #   person.errors.values   # => [["can not be nil", "must be specified"]]
         
     | 
| 
       169 
182 
     | 
    
         
             
                def values
         
     | 
| 
       170 
183 
     | 
    
         
             
                  messages.values
         
     | 
| 
       171 
184 
     | 
    
         
             
                end
         
     | 
| 
       172 
185 
     | 
    
         | 
| 
       173 
     | 
    
         
            -
                # Returns all message keys
         
     | 
| 
      
 186 
     | 
    
         
            +
                # Returns all message keys.
         
     | 
| 
      
 187 
     | 
    
         
            +
                #
         
     | 
| 
      
 188 
     | 
    
         
            +
                #   person.errors.messages # => {:name=>["can not be nil", "must be specified"]}
         
     | 
| 
      
 189 
     | 
    
         
            +
                #   person.errors.keys     # => [:name]
         
     | 
| 
       174 
190 
     | 
    
         
             
                def keys
         
     | 
| 
       175 
191 
     | 
    
         
             
                  messages.keys
         
     | 
| 
       176 
192 
     | 
    
         
             
                end
         
     | 
| 
       177 
193 
     | 
    
         | 
| 
       178 
     | 
    
         
            -
                # Returns an array of error messages, with the attribute name included
         
     | 
| 
      
 194 
     | 
    
         
            +
                # Returns an array of error messages, with the attribute name included.
         
     | 
| 
       179 
195 
     | 
    
         
             
                #
         
     | 
| 
       180 
     | 
    
         
            -
                #    
     | 
| 
       181 
     | 
    
         
            -
                #    
     | 
| 
       182 
     | 
    
         
            -
                #    
     | 
| 
      
 196 
     | 
    
         
            +
                #   person.errors.add(:name, "can't be blank")
         
     | 
| 
      
 197 
     | 
    
         
            +
                #   person.errors.add(:name, "must be specified")
         
     | 
| 
      
 198 
     | 
    
         
            +
                #   person.errors.to_a # => ["name can't be blank", "name must be specified"]
         
     | 
| 
       183 
199 
     | 
    
         
             
                def to_a
         
     | 
| 
       184 
200 
     | 
    
         
             
                  full_messages
         
     | 
| 
       185 
201 
     | 
    
         
             
                end
         
     | 
| 
       186 
202 
     | 
    
         | 
| 
       187 
203 
     | 
    
         
             
                # Returns the number of error messages.
         
     | 
| 
       188 
     | 
    
         
            -
                # 
     | 
| 
       189 
     | 
    
         
            -
                #    
     | 
| 
       190 
     | 
    
         
            -
                #    
     | 
| 
       191 
     | 
    
         
            -
                #    
     | 
| 
      
 204 
     | 
    
         
            +
                #
         
     | 
| 
      
 205 
     | 
    
         
            +
                #   person.errors.add(:name, "can't be blank")
         
     | 
| 
      
 206 
     | 
    
         
            +
                #   person.errors.count # => 1
         
     | 
| 
      
 207 
     | 
    
         
            +
                #   person.errors.add(:name, "must be specified")
         
     | 
| 
      
 208 
     | 
    
         
            +
                #   person.errors.count # => 2
         
     | 
| 
       192 
209 
     | 
    
         
             
                def count
         
     | 
| 
       193 
210 
     | 
    
         
             
                  to_a.size
         
     | 
| 
       194 
211 
     | 
    
         
             
                end
         
     | 
| 
       195 
212 
     | 
    
         | 
| 
       196 
     | 
    
         
            -
                # Returns true if no errors are found, false otherwise.
         
     | 
| 
      
 213 
     | 
    
         
            +
                # Returns +true+ if no errors are found, +false+ otherwise.
         
     | 
| 
       197 
214 
     | 
    
         
             
                # If the error message is a string it can be empty.
         
     | 
| 
      
 215 
     | 
    
         
            +
                #
         
     | 
| 
      
 216 
     | 
    
         
            +
                #   person.errors.full_messages # => ["name can not be nil"]
         
     | 
| 
      
 217 
     | 
    
         
            +
                #   person.errors.empty?        # => false
         
     | 
| 
       198 
218 
     | 
    
         
             
                def empty?
         
     | 
| 
       199 
219 
     | 
    
         
             
                  all? { |k, v| v && v.empty? && !v.is_a?(String) }
         
     | 
| 
       200 
220 
     | 
    
         
             
                end
         
     | 
| 
      
 221 
     | 
    
         
            +
                # aliases empty?
         
     | 
| 
       201 
222 
     | 
    
         
             
                alias_method :blank?, :empty?
         
     | 
| 
       202 
223 
     | 
    
         | 
| 
       203 
224 
     | 
    
         
             
                # Returns an xml formatted representation of the Errors hash.
         
     | 
| 
       204 
225 
     | 
    
         
             
                #
         
     | 
| 
       205 
     | 
    
         
            -
                #    
     | 
| 
       206 
     | 
    
         
            -
                #    
     | 
| 
       207 
     | 
    
         
            -
                #    
     | 
| 
      
 226 
     | 
    
         
            +
                #   person.errors.add(:name, "can't be blank")
         
     | 
| 
      
 227 
     | 
    
         
            +
                #   person.errors.add(:name, "must be specified")
         
     | 
| 
      
 228 
     | 
    
         
            +
                #   person.errors.to_xml
         
     | 
| 
       208 
229 
     | 
    
         
             
                #   # =>
         
     | 
| 
       209 
230 
     | 
    
         
             
                #   #  <?xml version=\"1.0\" encoding=\"UTF-8\"?>
         
     | 
| 
       210 
231 
     | 
    
         
             
                #   #  <errors>
         
     | 
| 
         @@ -212,54 +233,106 @@ module ActiveModel 
     | 
|
| 
       212 
233 
     | 
    
         
             
                #   #    <error>name must be specified</error>
         
     | 
| 
       213 
234 
     | 
    
         
             
                #   #  </errors>
         
     | 
| 
       214 
235 
     | 
    
         
             
                def to_xml(options={})
         
     | 
| 
       215 
     | 
    
         
            -
                  to_a.to_xml  
     | 
| 
      
 236 
     | 
    
         
            +
                  to_a.to_xml({ :root => "errors", :skip_types => true }.merge!(options))
         
     | 
| 
       216 
237 
     | 
    
         
             
                end
         
     | 
| 
       217 
238 
     | 
    
         | 
| 
       218 
     | 
    
         
            -
                # Returns  
     | 
| 
      
 239 
     | 
    
         
            +
                # Returns a Hash that can be used as the JSON representation for this
         
     | 
| 
      
 240 
     | 
    
         
            +
                # object. You can pass the <tt>:full_messages</tt> option. This determines
         
     | 
| 
      
 241 
     | 
    
         
            +
                # if the json object should contain full messages or not (false by default).
         
     | 
| 
      
 242 
     | 
    
         
            +
                #
         
     | 
| 
      
 243 
     | 
    
         
            +
                #   person.as_json                      # => {:name=>["can not be nil"]}
         
     | 
| 
      
 244 
     | 
    
         
            +
                #   person.as_json(full_messages: true) # => {:name=>["name can not be nil"]}
         
     | 
| 
       219 
245 
     | 
    
         
             
                def as_json(options=nil)
         
     | 
| 
       220 
     | 
    
         
            -
                  to_hash
         
     | 
| 
      
 246 
     | 
    
         
            +
                  to_hash(options && options[:full_messages])
         
     | 
| 
       221 
247 
     | 
    
         
             
                end
         
     | 
| 
       222 
248 
     | 
    
         | 
| 
       223 
     | 
    
         
            -
                 
     | 
| 
       224 
     | 
    
         
            -
             
     | 
| 
      
 249 
     | 
    
         
            +
                # Returns a Hash of attributes with their error messages. If +full_messages+
         
     | 
| 
      
 250 
     | 
    
         
            +
                # is +true+, it will contain full messages (see +full_message+).
         
     | 
| 
      
 251 
     | 
    
         
            +
                #
         
     | 
| 
      
 252 
     | 
    
         
            +
                #   person.to_hash       # => {:name=>["can not be nil"]}
         
     | 
| 
      
 253 
     | 
    
         
            +
                #   person.to_hash(true) # => {:name=>["name can not be nil"]}
         
     | 
| 
      
 254 
     | 
    
         
            +
                def to_hash(full_messages = false)
         
     | 
| 
      
 255 
     | 
    
         
            +
                  if full_messages
         
     | 
| 
      
 256 
     | 
    
         
            +
                    messages = {}
         
     | 
| 
      
 257 
     | 
    
         
            +
                    self.messages.each do |attribute, array|
         
     | 
| 
      
 258 
     | 
    
         
            +
                      messages[attribute] = array.map { |message| full_message(attribute, message) }
         
     | 
| 
      
 259 
     | 
    
         
            +
                    end
         
     | 
| 
      
 260 
     | 
    
         
            +
                    messages
         
     | 
| 
      
 261 
     | 
    
         
            +
                  else
         
     | 
| 
      
 262 
     | 
    
         
            +
                    self.messages.dup
         
     | 
| 
      
 263 
     | 
    
         
            +
                  end
         
     | 
| 
       225 
264 
     | 
    
         
             
                end
         
     | 
| 
       226 
265 
     | 
    
         | 
| 
       227 
     | 
    
         
            -
                # Adds +message+ to the error messages on +attribute+. More than one error 
     | 
| 
       228 
     | 
    
         
            -
                # +attribute+.
         
     | 
| 
       229 
     | 
    
         
            -
                #  
     | 
| 
      
 266 
     | 
    
         
            +
                # Adds +message+ to the error messages on +attribute+. More than one error
         
     | 
| 
      
 267 
     | 
    
         
            +
                # can be added to the same +attribute+. If no +message+ is supplied,
         
     | 
| 
      
 268 
     | 
    
         
            +
                # <tt>:invalid</tt> is assumed.
         
     | 
| 
      
 269 
     | 
    
         
            +
                #
         
     | 
| 
      
 270 
     | 
    
         
            +
                #   person.errors.add(:name)
         
     | 
| 
      
 271 
     | 
    
         
            +
                #   # => ["is invalid"]
         
     | 
| 
      
 272 
     | 
    
         
            +
                #   person.errors.add(:name, 'must be implemented')
         
     | 
| 
      
 273 
     | 
    
         
            +
                #   # => ["is invalid", "must be implemented"]
         
     | 
| 
       230 
274 
     | 
    
         
             
                #
         
     | 
| 
       231 
     | 
    
         
            -
                # 
     | 
| 
       232 
     | 
    
         
            -
                #  
     | 
| 
      
 275 
     | 
    
         
            +
                #   person.errors.messages
         
     | 
| 
      
 276 
     | 
    
         
            +
                #   # => {:name=>["must be implemented", "is invalid"]}
         
     | 
| 
      
 277 
     | 
    
         
            +
                #
         
     | 
| 
      
 278 
     | 
    
         
            +
                # If +message+ is a symbol, it will be translated using the appropriate
         
     | 
| 
      
 279 
     | 
    
         
            +
                # scope (see +generate_message+).
         
     | 
| 
      
 280 
     | 
    
         
            +
                #
         
     | 
| 
      
 281 
     | 
    
         
            +
                # If +message+ is a proc, it will be called, allowing for things like
         
     | 
| 
      
 282 
     | 
    
         
            +
                # <tt>Time.now</tt> to be used within an error.
         
     | 
| 
      
 283 
     | 
    
         
            +
                #
         
     | 
| 
      
 284 
     | 
    
         
            +
                # If the <tt>:strict</tt> option is set to true will raise
         
     | 
| 
      
 285 
     | 
    
         
            +
                # ActiveModel::StrictValidationFailed instead of adding the error.
         
     | 
| 
      
 286 
     | 
    
         
            +
                # <tt>:strict</tt> option can also be set to any other exception.
         
     | 
| 
      
 287 
     | 
    
         
            +
                #
         
     | 
| 
      
 288 
     | 
    
         
            +
                #   person.errors.add(:name, nil, strict: true)
         
     | 
| 
      
 289 
     | 
    
         
            +
                #   # => ActiveModel::StrictValidationFailed: name is invalid
         
     | 
| 
      
 290 
     | 
    
         
            +
                #   person.errors.add(:name, nil, strict: NameIsInvalid)
         
     | 
| 
      
 291 
     | 
    
         
            +
                #   # => NameIsInvalid: name is invalid
         
     | 
| 
      
 292 
     | 
    
         
            +
                #
         
     | 
| 
      
 293 
     | 
    
         
            +
                #   person.errors.messages # => {}
         
     | 
| 
       233 
294 
     | 
    
         
             
                def add(attribute, message = nil, options = {})
         
     | 
| 
       234 
295 
     | 
    
         
             
                  message = normalize_message(attribute, message, options)
         
     | 
| 
       235 
     | 
    
         
            -
                  if options[:strict]
         
     | 
| 
       236 
     | 
    
         
            -
                     
     | 
| 
      
 296 
     | 
    
         
            +
                  if exception = options[:strict]
         
     | 
| 
      
 297 
     | 
    
         
            +
                    exception = ActiveModel::StrictValidationFailed if exception == true
         
     | 
| 
      
 298 
     | 
    
         
            +
                    raise exception, full_message(attribute, message)
         
     | 
| 
       237 
299 
     | 
    
         
             
                  end
         
     | 
| 
       238 
300 
     | 
    
         | 
| 
       239 
301 
     | 
    
         
             
                  self[attribute] << message
         
     | 
| 
       240 
302 
     | 
    
         
             
                end
         
     | 
| 
       241 
303 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                # Will add an error message to each of the attributes in +attributes+ 
     | 
| 
      
 304 
     | 
    
         
            +
                # Will add an error message to each of the attributes in +attributes+
         
     | 
| 
      
 305 
     | 
    
         
            +
                # that is empty.
         
     | 
| 
      
 306 
     | 
    
         
            +
                #
         
     | 
| 
      
 307 
     | 
    
         
            +
                #   person.errors.add_on_empty(:name)
         
     | 
| 
      
 308 
     | 
    
         
            +
                #   person.errors.messages
         
     | 
| 
      
 309 
     | 
    
         
            +
                #   # => {:name=>["can't be empty"]}
         
     | 
| 
       243 
310 
     | 
    
         
             
                def add_on_empty(attributes, options = {})
         
     | 
| 
       244 
     | 
    
         
            -
                   
     | 
| 
      
 311 
     | 
    
         
            +
                  Array(attributes).each do |attribute|
         
     | 
| 
       245 
312 
     | 
    
         
             
                    value = @base.send(:read_attribute_for_validation, attribute)
         
     | 
| 
       246 
313 
     | 
    
         
             
                    is_empty = value.respond_to?(:empty?) ? value.empty? : false
         
     | 
| 
       247 
314 
     | 
    
         
             
                    add(attribute, :empty, options) if value.nil? || is_empty
         
     | 
| 
       248 
315 
     | 
    
         
             
                  end
         
     | 
| 
       249 
316 
     | 
    
         
             
                end
         
     | 
| 
       250 
317 
     | 
    
         | 
| 
       251 
     | 
    
         
            -
                # Will add an error message to each of the attributes in +attributes+ that 
     | 
| 
      
 318 
     | 
    
         
            +
                # Will add an error message to each of the attributes in +attributes+ that
         
     | 
| 
      
 319 
     | 
    
         
            +
                # is blank (using Object#blank?).
         
     | 
| 
      
 320 
     | 
    
         
            +
                #
         
     | 
| 
      
 321 
     | 
    
         
            +
                #   person.errors.add_on_blank(:name)
         
     | 
| 
      
 322 
     | 
    
         
            +
                #   person.errors.messages
         
     | 
| 
      
 323 
     | 
    
         
            +
                #   # => {:name=>["can't be blank"]}
         
     | 
| 
       252 
324 
     | 
    
         
             
                def add_on_blank(attributes, options = {})
         
     | 
| 
       253 
     | 
    
         
            -
                   
     | 
| 
      
 325 
     | 
    
         
            +
                  Array(attributes).each do |attribute|
         
     | 
| 
       254 
326 
     | 
    
         
             
                    value = @base.send(:read_attribute_for_validation, attribute)
         
     | 
| 
       255 
327 
     | 
    
         
             
                    add(attribute, :blank, options) if value.blank?
         
     | 
| 
       256 
328 
     | 
    
         
             
                  end
         
     | 
| 
       257 
329 
     | 
    
         
             
                end
         
     | 
| 
       258 
330 
     | 
    
         | 
| 
       259 
     | 
    
         
            -
                # Returns true if an error on the attribute with the given message is 
     | 
| 
       260 
     | 
    
         
            -
                # +message+ is treated the same as for +add+.
         
     | 
| 
       261 
     | 
    
         
            -
                # 
     | 
| 
       262 
     | 
    
         
            -
                #    
     | 
| 
      
 331 
     | 
    
         
            +
                # Returns +true+ if an error on the attribute with the given message is
         
     | 
| 
      
 332 
     | 
    
         
            +
                # present, +false+ otherwise. +message+ is treated the same as for +add+.
         
     | 
| 
      
 333 
     | 
    
         
            +
                #
         
     | 
| 
      
 334 
     | 
    
         
            +
                #   person.errors.add :name, :blank
         
     | 
| 
      
 335 
     | 
    
         
            +
                #   person.errors.added? :name, :blank # => true
         
     | 
| 
       263 
336 
     | 
    
         
             
                def added?(attribute, message = nil, options = {})
         
     | 
| 
       264 
337 
     | 
    
         
             
                  message = normalize_message(attribute, message, options)
         
     | 
| 
       265 
338 
     | 
    
         
             
                  self[attribute].include? message
         
     | 
| 
         @@ -267,25 +340,24 @@ module ActiveModel 
     | 
|
| 
       267 
340 
     | 
    
         | 
| 
       268 
341 
     | 
    
         
             
                # Returns all the full error messages in an array.
         
     | 
| 
       269 
342 
     | 
    
         
             
                #
         
     | 
| 
       270 
     | 
    
         
            -
                #   class  
     | 
| 
      
 343 
     | 
    
         
            +
                #   class Person
         
     | 
| 
       271 
344 
     | 
    
         
             
                #     validates_presence_of :name, :address, :email
         
     | 
| 
       272 
     | 
    
         
            -
                #     validates_length_of :name, : 
     | 
| 
      
 345 
     | 
    
         
            +
                #     validates_length_of :name, in: 5..30
         
     | 
| 
       273 
346 
     | 
    
         
             
                #   end
         
     | 
| 
       274 
347 
     | 
    
         
             
                #
         
     | 
| 
       275 
     | 
    
         
            -
                #    
     | 
| 
       276 
     | 
    
         
            -
                #    
     | 
| 
       277 
     | 
    
         
            -
                # 
     | 
| 
      
 348 
     | 
    
         
            +
                #   person = Person.create(address: '123 First St.')
         
     | 
| 
      
 349 
     | 
    
         
            +
                #   person.errors.full_messages
         
     | 
| 
      
 350 
     | 
    
         
            +
                #   # => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
         
     | 
| 
       278 
351 
     | 
    
         
             
                def full_messages
         
     | 
| 
       279 
352 
     | 
    
         
             
                  map { |attribute, message| full_message(attribute, message) }
         
     | 
| 
       280 
353 
     | 
    
         
             
                end
         
     | 
| 
       281 
354 
     | 
    
         | 
| 
       282 
355 
     | 
    
         
             
                # Returns a full message for a given attribute.
         
     | 
| 
       283 
356 
     | 
    
         
             
                #
         
     | 
| 
       284 
     | 
    
         
            -
                #    
     | 
| 
       285 
     | 
    
         
            -
                #     "Name is invalid"
         
     | 
| 
      
 357 
     | 
    
         
            +
                #   person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
         
     | 
| 
       286 
358 
     | 
    
         
             
                def full_message(attribute, message)
         
     | 
| 
       287 
359 
     | 
    
         
             
                  return message if attribute == :base
         
     | 
| 
       288 
     | 
    
         
            -
                  attr_name = attribute.to_s. 
     | 
| 
      
 360 
     | 
    
         
            +
                  attr_name = attribute.to_s.tr('.', '_').humanize
         
     | 
| 
       289 
361 
     | 
    
         
             
                  attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
         
     | 
| 
       290 
362 
     | 
    
         
             
                  I18n.t(:"errors.format", {
         
     | 
| 
       291 
363 
     | 
    
         
             
                    :default   => "%{attribute} %{message}",
         
     | 
| 
         @@ -298,10 +370,11 @@ module ActiveModel 
     | 
|
| 
       298 
370 
     | 
    
         
             
                # (<tt>activemodel.errors.messages</tt>).
         
     | 
| 
       299 
371 
     | 
    
         
             
                #
         
     | 
| 
       300 
372 
     | 
    
         
             
                # Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>,
         
     | 
| 
       301 
     | 
    
         
            -
                # if it's not there, it's looked up in <tt>models.MODEL.MESSAGE</tt> and if 
     | 
| 
       302 
     | 
    
         
            -
                # there also, it returns the translation of the default message
         
     | 
| 
       303 
     | 
    
         
            -
                # (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model 
     | 
| 
       304 
     | 
    
         
            -
                # translated attribute name and the value are available for 
     | 
| 
      
 373 
     | 
    
         
            +
                # if it's not there, it's looked up in <tt>models.MODEL.MESSAGE</tt> and if
         
     | 
| 
      
 374 
     | 
    
         
            +
                # that is not there also, it returns the translation of the default message
         
     | 
| 
      
 375 
     | 
    
         
            +
                # (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model
         
     | 
| 
      
 376 
     | 
    
         
            +
                # name, translated attribute name and the value are available for
         
     | 
| 
      
 377 
     | 
    
         
            +
                # interpolation.
         
     | 
| 
       305 
378 
     | 
    
         
             
                #
         
     | 
| 
       306 
379 
     | 
    
         
             
                # When using inheritance in your models, it will check all the inherited
         
     | 
| 
       307 
380 
     | 
    
         
             
                # models too, but only if the model itself hasn't been found. Say you have
         
     | 
| 
         @@ -317,7 +390,6 @@ module ActiveModel 
     | 
|
| 
       317 
390 
     | 
    
         
             
                # * <tt>activemodel.errors.messages.blank</tt>
         
     | 
| 
       318 
391 
     | 
    
         
             
                # * <tt>errors.attributes.title.blank</tt>
         
     | 
| 
       319 
392 
     | 
    
         
             
                # * <tt>errors.messages.blank</tt>
         
     | 
| 
       320 
     | 
    
         
            -
                #
         
     | 
| 
       321 
393 
     | 
    
         
             
                def generate_message(attribute, type = :invalid, options = {})
         
     | 
| 
       322 
394 
     | 
    
         
             
                  type = options.delete(:message) if options[:message].is_a?(Symbol)
         
     | 
| 
       323 
395 
     | 
    
         | 
| 
         @@ -346,7 +418,7 @@ module ActiveModel 
     | 
|
| 
       346 
418 
     | 
    
         
             
                    :model => @base.class.model_name.human,
         
     | 
| 
       347 
419 
     | 
    
         
             
                    :attribute => @base.class.human_attribute_name(attribute),
         
     | 
| 
       348 
420 
     | 
    
         
             
                    :value => value
         
     | 
| 
       349 
     | 
    
         
            -
                  }.merge(options)
         
     | 
| 
      
 421 
     | 
    
         
            +
                  }.merge!(options)
         
     | 
| 
       350 
422 
     | 
    
         | 
| 
       351 
423 
     | 
    
         
             
                  I18n.translate(key, options)
         
     | 
| 
       352 
424 
     | 
    
         
             
                end
         
     | 
| 
         @@ -355,9 +427,10 @@ module ActiveModel 
     | 
|
| 
       355 
427 
     | 
    
         
             
                def normalize_message(attribute, message, options)
         
     | 
| 
       356 
428 
     | 
    
         
             
                  message ||= :invalid
         
     | 
| 
       357 
429 
     | 
    
         | 
| 
       358 
     | 
    
         
            -
                   
     | 
| 
      
 430 
     | 
    
         
            +
                  case message
         
     | 
| 
      
 431 
     | 
    
         
            +
                  when Symbol
         
     | 
| 
       359 
432 
     | 
    
         
             
                    generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS))
         
     | 
| 
       360 
     | 
    
         
            -
                   
     | 
| 
      
 433 
     | 
    
         
            +
                  when Proc
         
     | 
| 
       361 
434 
     | 
    
         
             
                    message.call
         
     | 
| 
       362 
435 
     | 
    
         
             
                  else
         
     | 
| 
       363 
436 
     | 
    
         
             
                    message
         
     | 
| 
         @@ -365,6 +438,21 @@ module ActiveModel 
     | 
|
| 
       365 
438 
     | 
    
         
             
                end
         
     | 
| 
       366 
439 
     | 
    
         
             
              end
         
     | 
| 
       367 
440 
     | 
    
         | 
| 
      
 441 
     | 
    
         
            +
              # Raised when a validation cannot be corrected by end users and are considered
         
     | 
| 
      
 442 
     | 
    
         
            +
              # exceptional.
         
     | 
| 
      
 443 
     | 
    
         
            +
              #
         
     | 
| 
      
 444 
     | 
    
         
            +
              #   class Person
         
     | 
| 
      
 445 
     | 
    
         
            +
              #     include ActiveModel::Validations
         
     | 
| 
      
 446 
     | 
    
         
            +
              #
         
     | 
| 
      
 447 
     | 
    
         
            +
              #     attr_accessor :name
         
     | 
| 
      
 448 
     | 
    
         
            +
              #
         
     | 
| 
      
 449 
     | 
    
         
            +
              #     validates_presence_of :name, strict: true
         
     | 
| 
      
 450 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 451 
     | 
    
         
            +
              #
         
     | 
| 
      
 452 
     | 
    
         
            +
              #   person = Person.new
         
     | 
| 
      
 453 
     | 
    
         
            +
              #   person.name = nil
         
     | 
| 
      
 454 
     | 
    
         
            +
              #   person.valid?
         
     | 
| 
      
 455 
     | 
    
         
            +
              #   # => ActiveModel::StrictValidationFailed: Name can't be blank
         
     | 
| 
       368 
456 
     | 
    
         
             
              class StrictValidationFailed < StandardError
         
     | 
| 
       369 
457 
     | 
    
         
             
              end
         
     | 
| 
       370 
458 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveModel
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Raised when forbidden attributes are used for mass assignment.
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              #   class Person < ActiveRecord::Base
         
     | 
| 
      
 5 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 6 
     | 
    
         
            +
              #
         
     | 
| 
      
 7 
     | 
    
         
            +
              #   params = ActionController::Parameters.new(name: 'Bob')
         
     | 
| 
      
 8 
     | 
    
         
            +
              #   Person.new(params)
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   # => ActiveModel::ForbiddenAttributesError
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              #   params.permit!
         
     | 
| 
      
 12 
     | 
    
         
            +
              #   Person.new(params)
         
     | 
| 
      
 13 
     | 
    
         
            +
              #   # => #<Person id: nil, name: "Bob">
         
     | 
| 
      
 14 
     | 
    
         
            +
              class ForbiddenAttributesError < StandardError
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              module ForbiddenAttributesProtection # :nodoc:
         
     | 
| 
      
 18 
     | 
    
         
            +
                protected
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def sanitize_for_mass_assignment(attributes)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    if attributes.respond_to?(:permitted?) && !attributes.permitted?
         
     | 
| 
      
 21 
     | 
    
         
            +
                      raise ActiveModel::ForbiddenAttributesError
         
     | 
| 
      
 22 
     | 
    
         
            +
                    else
         
     | 
| 
      
 23 
     | 
    
         
            +
                      attributes
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     |