aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/lib/active_model')
-rw-r--r--activemodel/lib/active_model/conversion.rb17
-rw-r--r--activemodel/lib/active_model/dirty.rb69
-rw-r--r--activemodel/lib/active_model/errors.rb8
-rw-r--r--activemodel/lib/active_model/forbidden_attributes_protection.rb1
-rw-r--r--activemodel/lib/active_model/gem_version.rb4
-rw-r--r--activemodel/lib/active_model/lint.rb11
-rw-r--r--activemodel/lib/active_model/locale/en.yml12
-rw-r--r--activemodel/lib/active_model/model.rb20
-rw-r--r--activemodel/lib/active_model/naming.rb20
-rw-r--r--activemodel/lib/active_model/secure_password.rb37
-rw-r--r--activemodel/lib/active_model/serialization.rb16
-rw-r--r--activemodel/lib/active_model/serializers/json.rb2
-rw-r--r--activemodel/lib/active_model/serializers/xml.rb2
-rw-r--r--activemodel/lib/active_model/validations.rb7
-rw-r--r--activemodel/lib/active_model/validations/confirmation.rb2
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb14
-rw-r--r--activemodel/lib/active_model/validator.rb18
17 files changed, 172 insertions, 88 deletions
diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb
index 374265f0d8..9c9b6f4a77 100644
--- a/activemodel/lib/active_model/conversion.rb
+++ b/activemodel/lib/active_model/conversion.rb
@@ -40,13 +40,15 @@ module ActiveModel
self
end
- # Returns an Enumerable of all key attributes if any is set, regardless if
+ # Returns an Array of all key attributes if any is set, regardless if
# the object is persisted or not. Returns +nil+ if there are no key attributes.
#
- # class Person < ActiveRecord::Base
+ # class Person
+ # include ActiveModel::Conversion
+ # attr_accessor :id
# end
#
- # person = Person.create
+ # person = Person.create(id: 1)
# person.to_key # => [1]
def to_key
key = respond_to?(:id) && id
@@ -56,10 +58,15 @@ module ActiveModel
# Returns a +string+ representing the object's key suitable for use in URLs,
# or +nil+ if <tt>persisted?</tt> is +false+.
#
- # class Person < ActiveRecord::Base
+ # class Person
+ # include ActiveModel::Conversion
+ # attr_accessor :id
+ # def persisted?
+ # true
+ # end
# end
#
- # person = Person.create
+ # person = Person.create(id: 1)
# person.to_param # => "1"
def to_param
(persisted? && key = to_key) ? key.join('-') : nil
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 98ffffeb10..ca04f48c1c 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -15,8 +15,9 @@ module ActiveModel
# * Call <tt>attr_name_will_change!</tt> before each change to the tracked
# attribute.
# * Call <tt>changes_applied</tt> after the changes are persisted.
- # * Call <tt>reset_changes</tt> when you want to reset the changes
+ # * Call <tt>clear_changes_information</tt> when you want to reset the changes
# information.
+ # * Call <tt>restore_attributes</tt> when you want to restore previous data.
#
# A minimal implementation could be:
#
@@ -36,11 +37,18 @@ module ActiveModel
#
# def save
# # do persistence work
+ #
# changes_applied
# end
#
# def reload!
- # reset_changes
+ # # get the values from the persistence layer
+ #
+ # clear_changes_information
+ # end
+ #
+ # def rollback!
+ # restore_attributes
# end
# end
#
@@ -72,6 +80,13 @@ module ActiveModel
# person.reload!
# person.previous_changes # => {}
#
+ # Rollback the changes:
+ #
+ # person.name = "Uncle Bob"
+ # person.rollback!
+ # person.name # => "Bill"
+ # person.name_changed? # => false
+ #
# Assigning the same value leaves the attribute unchanged:
#
# person.name = 'Bill'
@@ -84,9 +99,11 @@ module ActiveModel
# person.changed # => ["name"]
# person.changes # => {"name" => ["Bill", "Bob"]}
#
- # If an attribute is modified in-place then make use of <tt>[attribute_name]_will_change!</tt>
- # to mark that the attribute is changing. Otherwise ActiveModel can't track
- # changes to in-place attributes.
+ # If an attribute is modified in-place then make use of
+ # +[attribute_name]_will_change!+ to mark that the attribute is changing.
+ # Otherwise Active Model can't track changes to in-place attributes. Note
+ # that Active Record can detect in-place modifications automatically. You do
+ # not need to call +[attribute_name]_will_change!+ on Active Record models.
#
# person.name_will_change!
# person.name_change # => ["Bill", "Bill"]
@@ -99,6 +116,7 @@ module ActiveModel
included do
attribute_method_suffix '_changed?', '_change', '_will_change!', '_was'
attribute_method_affix prefix: 'reset_', suffix: '!'
+ attribute_method_affix prefix: 'restore_', suffix: '!'
end
# Returns +true+ if any attribute have unsaved changes, +false+ otherwise.
@@ -162,20 +180,30 @@ module ActiveModel
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
end
+ # Restore all previous data of the provided attributes.
+ def restore_attributes(attributes = changed)
+ attributes.each { |attr| restore_attribute! attr }
+ end
+
private
# Removes current changes and makes them accessible through +previous_changes+.
- def changes_applied
+ def changes_applied # :doc:
@previously_changed = changes
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end
- # Removes all dirty data: current changes and previous changes
- def reset_changes
+ # Clear all dirty data: current changes and previous changes.
+ def clear_changes_information # :doc:
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end
+ def reset_changes
+ ActiveSupport::Deprecation.warn "#reset_changes is deprecated and will be removed on Rails 5. Please use #clear_changes_information instead."
+ clear_changes_information
+ end
+
# Handle <tt>*_change</tt> for +method_missing+.
def attribute_change(attr)
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
@@ -191,15 +219,36 @@ module ActiveModel
rescue TypeError, NoMethodError
end
- changed_attributes[attr] = value
+ set_attribute_was(attr, value)
end
# Handle <tt>reset_*!</tt> for +method_missing+.
def reset_attribute!(attr)
+ ActiveSupport::Deprecation.warn "#reset_#{attr}! is deprecated and will be removed on Rails 5. Please use #restore_#{attr}! instead."
+
+ restore_attribute!(attr)
+ end
+
+ # Handle <tt>restore_*!</tt> for +method_missing+.
+ def restore_attribute!(attr)
if attribute_changed?(attr)
__send__("#{attr}=", changed_attributes[attr])
- changed_attributes.delete(attr)
+ clear_attribute_changes([attr])
end
end
+
+ # This is necessary because `changed_attributes` might be overridden in
+ # other implemntations (e.g. in `ActiveRecord`)
+ alias_method :attributes_changed_by_setter, :changed_attributes # :nodoc:
+
+ # Force an attribute to have a particular "before" value
+ def set_attribute_was(attr, old_value)
+ attributes_changed_by_setter[attr] = old_value
+ end
+
+ # Remove changes information for the provided attributes.
+ def clear_attribute_changes(attributes)
+ attributes_changed_by_setter.except!(*attributes)
+ end
end
end
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 917d3b9142..1b46727351 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -23,7 +23,7 @@ module ActiveModel
# attr_reader :errors
#
# def validate!
- # errors.add(:name, "cannot be nil") if name == nil
+ # errors.add(:name, "cannot be nil") if name.nil?
# end
#
# # The following methods are needed to be minimally implemented
@@ -251,11 +251,9 @@ module ActiveModel
# person.errors.to_hash(true) # => {:name=>["name cannot be nil"]}
def to_hash(full_messages = false)
if full_messages
- messages = {}
- self.messages.each do |attribute, array|
+ self.messages.each_with_object({}) do |(attribute, array), messages|
messages[attribute] = array.map { |message| full_message(attribute, message) }
end
- messages
else
self.messages.dup
end
@@ -434,7 +432,7 @@ module ActiveModel
options = {
default: defaults,
- model: @base.class.model_name.human,
+ model: @base.model_name.human,
attribute: @base.class.human_attribute_name(attribute),
value: value
}.merge!(options)
diff --git a/activemodel/lib/active_model/forbidden_attributes_protection.rb b/activemodel/lib/active_model/forbidden_attributes_protection.rb
index 7468f95548..b4fa378601 100644
--- a/activemodel/lib/active_model/forbidden_attributes_protection.rb
+++ b/activemodel/lib/active_model/forbidden_attributes_protection.rb
@@ -23,5 +23,6 @@ module ActiveModel
attributes
end
end
+ alias :sanitize_forbidden_attributes :sanitize_for_mass_assignment
end
end
diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb
index 964b24398d..dd652190f7 100644
--- a/activemodel/lib/active_model/gem_version.rb
+++ b/activemodel/lib/active_model/gem_version.rb
@@ -1,5 +1,5 @@
module ActiveModel
- # Returns the version of the currently loaded ActiveModel as a <tt>Gem::Version</tt>
+ # Returns the version of the currently loaded Active Model as a <tt>Gem::Version</tt>
def self.gem_version
Gem::Version.new VERSION::STRING
end
@@ -8,7 +8,7 @@ module ActiveModel
MAJOR = 4
MINOR = 2
TINY = 0
- PRE = "alpha"
+ PRE = "beta1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb
index c6bc18b008..38087521a2 100644
--- a/activemodel/lib/active_model/lint.rb
+++ b/activemodel/lib/active_model/lint.rb
@@ -73,16 +73,19 @@ module ActiveModel
# == \Naming
#
- # Model.model_name must return a string with some convenience methods:
- # <tt>:human</tt>, <tt>:singular</tt> and <tt>:plural</tt>. Check
- # ActiveModel::Naming for more information.
+ # Model.model_name and Model#model_name must return a string with some
+ # convenience methods: # <tt>:human</tt>, <tt>:singular</tt> and
+ # <tt>:plural</tt>. Check ActiveModel::Naming for more information.
def test_model_naming
- assert model.class.respond_to?(:model_name), "The model should respond to model_name"
+ assert model.class.respond_to?(:model_name), "The model class should respond to model_name"
model_name = model.class.model_name
assert model_name.respond_to?(:to_str)
assert model_name.human.respond_to?(:to_str)
assert model_name.singular.respond_to?(:to_str)
assert model_name.plural.respond_to?(:to_str)
+
+ assert model.respond_to?(:model_name), "The model instance should respond to model_name"
+ assert_equal model.model_name, model.class.model_name
end
# == \Errors Testing
diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml
index 540e8132d3..bf07945fe1 100644
--- a/activemodel/lib/active_model/locale/en.yml
+++ b/activemodel/lib/active_model/locale/en.yml
@@ -14,9 +14,15 @@ en:
empty: "can't be empty"
blank: "can't be blank"
present: "must be blank"
- too_long: "is too long (maximum is %{count} characters)"
- too_short: "is too short (minimum is %{count} characters)"
- wrong_length: "is the wrong length (should be %{count} characters)"
+ too_long:
+ one: "is too long (maximum is 1 character)"
+ other: "is too long (maximum is %{count} characters)"
+ too_short:
+ one: "is too short (minimum is 1 character)"
+ other: "is too short (minimum is %{count} characters)"
+ wrong_length:
+ one: "is the wrong length (should be 1 character)"
+ other: "is the wrong length (should be %{count} characters)"
not_a_number: "is not a number"
not_an_integer: "must be an integer"
greater_than: "must be greater than %{count}"
diff --git a/activemodel/lib/active_model/model.rb b/activemodel/lib/active_model/model.rb
index 63716eebb1..d51d6ddcc9 100644
--- a/activemodel/lib/active_model/model.rb
+++ b/activemodel/lib/active_model/model.rb
@@ -16,8 +16,8 @@ module ActiveModel
# end
#
# person = Person.new(name: 'bob', age: '18')
- # person.name # => 'bob'
- # person.age # => 18
+ # person.name # => "bob"
+ # person.age # => "18"
#
# Note that, by default, <tt>ActiveModel::Model</tt> implements <tt>persisted?</tt>
# to return +false+, which is the most common case. You may want to override
@@ -56,13 +56,13 @@ module ActiveModel
# refer to the specific modules included in <tt>ActiveModel::Model</tt>
# (see below).
module Model
- def self.included(base) #:nodoc:
- base.class_eval do
- extend ActiveModel::Naming
- extend ActiveModel::Translation
- include ActiveModel::Validations
- include ActiveModel::Conversion
- end
+ extend ActiveSupport::Concern
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+
+ included do
+ extend ActiveModel::Naming
+ extend ActiveModel::Translation
end
# Initializes a new model with the given +params+.
@@ -74,7 +74,7 @@ module ActiveModel
#
# person = Person.new(name: 'bob', age: '18')
# person.name # => "bob"
- # person.age # => 18
+ # person.age # => "18"
def initialize(params={})
params.each do |attr, value|
self.public_send("#{attr}=", value)
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index 11ebfe6cc0..4e6b02c246 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -204,7 +204,7 @@ module ActiveModel
# extend ActiveModel::Naming
# end
#
- # BookCover.model_name # => "BookCover"
+ # BookCover.model_name.name # => "BookCover"
# BookCover.model_name.human # => "Book cover"
#
# BookCover.model_name.i18n_key # => :book_cover
@@ -214,14 +214,20 @@ module ActiveModel
# is required to pass the Active Model Lint test. So either extending the
# provided method below, or rolling your own is required.
module Naming
+ def self.extended(base) #:nodoc:
+ base.remove_possible_method :model_name
+ base.delegate :model_name, to: :class
+ end
+
# Returns an ActiveModel::Name object for module. It can be
# used to retrieve all kinds of naming-related information
# (See ActiveModel::Name for more information).
#
- # class Person < ActiveModel::Model
+ # class Person
+ # include ActiveModel::Model
# end
#
- # Person.model_name # => Person
+ # Person.model_name.name # => "Person"
# Person.model_name.class # => ActiveModel::Name
# Person.model_name.singular # => "person"
# Person.model_name.plural # => "people"
@@ -298,12 +304,10 @@ module ActiveModel
end
def self.model_name_from_record_or_class(record_or_class) #:nodoc:
- if record_or_class.respond_to?(:model_name)
- record_or_class.model_name
- elsif record_or_class.respond_to?(:to_model)
- record_or_class.to_model.class.model_name
+ if record_or_class.respond_to?(:to_model)
+ record_or_class.to_model.model_name
else
- record_or_class.class.model_name
+ record_or_class.model_name
end
end
private_class_method :model_name_from_record_or_class
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb
index 826e89bf9d..f6ad35769f 100644
--- a/activemodel/lib/active_model/secure_password.rb
+++ b/activemodel/lib/active_model/secure_password.rb
@@ -2,6 +2,11 @@ module ActiveModel
module SecurePassword
extend ActiveSupport::Concern
+ # BCrypt hash function can handle maximum 72 characters, and if we pass
+ # password of length more than 72 characters it ignores extra characters.
+ # Hence need to put a restriction on password length.
+ MAX_PASSWORD_LENGTH_ALLOWED = 72
+
class << self
attr_accessor :min_cost # :nodoc:
end
@@ -11,16 +16,20 @@ module ActiveModel
# Adds methods to set and authenticate against a BCrypt password.
# This mechanism requires you to have a +password_digest+ attribute.
#
- # Validations for presence of password on create, confirmation of password
- # (using a +password_confirmation+ attribute) are automatically added. If
- # you wish to turn off validations, pass <tt>validations: false</tt> as an
- # argument. You can add more validations by hand if need be.
+ # The following validations are added automatically:
+ # * Password must be present on creation
+ # * Password length should be less than or equal to 72 characters
+ # * Confirmation of password (using a +password_confirmation+ attribute)
+ #
+ # If password confirmation validation is not needed, simply leave out the
+ # value for +password_confirmation+ (i.e. don't provide a form field for
+ # it). When this attribute has a +nil+ value, the validation will not be
+ # triggered.
#
- # If you don't need the confirmation validation, just don't set any
- # value to the password_confirmation attribute and the validation
- # will not be triggered.
+ # For further customizability, it is possible to supress the default
+ # validations by passing <tt>validations: false</tt> as an argument.
#
- # You need to add bcrypt (~> 3.1.7) to Gemfile to use #has_secure_password:
+ # Add bcrypt (~> 3.1.7) to Gemfile to use #has_secure_password:
#
# gem 'bcrypt', '~> 3.1.7'
#
@@ -52,11 +61,11 @@ module ActiveModel
raise
end
- attr_reader :password
-
include InstanceMethodsOnActivation
if options.fetch(:validations, true)
+ include ActiveModel::Validations
+
# This ensures the model has a password by checking whether the password_digest
# is present, so that this works with both new and existing records. However,
# when there is an error, the message is added to the password attribute instead
@@ -65,9 +74,11 @@ module ActiveModel
record.errors.add(:password, :blank) unless record.password_digest.present?
end
+ validates_length_of :password, maximum: ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED
validates_confirmation_of :password, if: ->{ password.present? }
end
+ # This code is necessary as long as the protected_attributes gem is supported.
if respond_to?(:attributes_protected_by_default)
def self.attributes_protected_by_default #:nodoc:
super + ['password_digest']
@@ -91,8 +102,10 @@ module ActiveModel
BCrypt::Password.new(password_digest) == unencrypted_password && self
end
+ attr_reader :password
+
# Encrypts the password into the +password_digest+ attribute, only if the
- # new password is not blank.
+ # new password is not empty.
#
# class User < ActiveRecord::Base
# has_secure_password validations: false
@@ -106,7 +119,7 @@ module ActiveModel
def password=(unencrypted_password)
if unencrypted_password.nil?
self.password_digest = nil
- elsif unencrypted_password.present?
+ elsif !unencrypted_password.empty?
@password = unencrypted_password
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost)
diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb
index 36a6c00290..976f50b13e 100644
--- a/activemodel/lib/active_model/serialization.rb
+++ b/activemodel/lib/active_model/serialization.rb
@@ -4,7 +4,7 @@ require 'active_support/core_ext/hash/slice'
module ActiveModel
# == Active \Model \Serialization
#
- # Provides a basic serialization to a serializable_hash for your object.
+ # Provides a basic serialization to a serializable_hash for your objects.
#
# A minimal implementation could be:
#
@@ -25,14 +25,14 @@ module ActiveModel
# person.name = "Bob"
# person.serializable_hash # => {"name"=>"Bob"}
#
- # You need to declare an attributes hash which contains the attributes you
- # want to serialize. Attributes must be strings, not symbols. When called,
- # serializable hash will use instance methods that match the name of the
- # attributes hash's keys. In order to override this behavior, take a look at
- # the private method +read_attribute_for_serialization+.
+ # An +attributes+ hash must be defined and should contain any attributes you
+ # need to be serialized. Attributes must be strings, not symbols.
+ # When called, serializable hash will use instance methods that match the name
+ # of the attributes hash's keys. In order to override this behavior, take a look
+ # at the private method +read_attribute_for_serialization+.
#
- # Most of the time though, you will want to include the JSON or XML
- # serializations. Both of these modules automatically include the
+ # Most of the time though, either the JSON or XML serializations are needed.
+ # Both of these modules automatically include the
# <tt>ActiveModel::Serialization</tt> module, so there is no need to
# explicitly include it.
#
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index c58e73f6a7..77f2a64b11 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -93,7 +93,7 @@ module ActiveModel
end
if root
- root = self.class.model_name.element if root == true
+ root = model_name.element if root == true
{ root => serializable_hash(options) }
else
serializable_hash(options)
diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb
index 7f99536dbb..3ad3bf30ad 100644
--- a/activemodel/lib/active_model/serializers/xml.rb
+++ b/activemodel/lib/active_model/serializers/xml.rb
@@ -84,7 +84,7 @@ module ActiveModel
@builder = options[:builder]
@builder.instruct! unless options[:skip_instruct]
- root = (options[:root] || @serializable.class.model_name.element).to_s
+ root = (options[:root] || @serializable.model_name.element).to_s
root = ActiveSupport::XmlMini.rename_key(root, options)
args = [root]
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index cf97f45dba..7ee033ba5f 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -39,6 +39,7 @@ module ActiveModel
extend ActiveSupport::Concern
included do
+ extend ActiveModel::Naming
extend ActiveModel::Callbacks
extend ActiveModel::Translation
@@ -141,6 +142,11 @@ module ActiveModel
# value.
def validate(*args, &block)
options = args.extract_options!
+
+ if args.all? { |arg| arg.is_a?(Symbol) }
+ options.assert_valid_keys([:on, :if, :unless])
+ end
+
if options.key?(:on)
options = options.dup
options[:if] = Array(options[:if])
@@ -148,6 +154,7 @@ module ActiveModel
Array(options[:on]).include?(o.validation_context)
}
end
+
args << options
set_callback(:validate, *args, &block)
end
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index a51523912f..1b11c28087 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -54,7 +54,7 @@ module ActiveModel
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "doesn't match
- # confirmation").
+ # <tt>%{translated_attribute_name}</tt>").
#
# There is also a list of default options supported by every validator:
# +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index a9fb9804d4..5bd162433d 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -30,7 +30,7 @@ module ActiveModel
return
end
- if options[:only_integer]
+ if allow_only_integer?(record)
unless value = parse_raw_value_as_an_integer(raw_value)
record.errors.add(attr_name, :not_an_integer, filtered_options(raw_value))
return
@@ -75,6 +75,17 @@ module ActiveModel
filtered[:value] = value
filtered
end
+
+ def allow_only_integer?(record)
+ case options[:only_integer]
+ when Symbol
+ record.send(options[:only_integer])
+ when Proc
+ options[:only_integer].call(record)
+ else
+ options[:only_integer]
+ end
+ end
end
module HelperMethods
@@ -121,6 +132,7 @@ module ActiveModel
# * <tt>:equal_to</tt>
# * <tt>:less_than</tt>
# * <tt>:less_than_or_equal_to</tt>
+ # * <tt>:only_integer</tt>
#
# For example:
#
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index bddacc8c45..0116de68ab 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -79,7 +79,7 @@ module ActiveModel
# include ActiveModel::Validations
# attr_accessor :title
#
- # validates :title, presence: true
+ # validates :title, presence: true, title: true
# end
#
# It can be useful to access the class that is using that validator when there are prerequisites such
@@ -106,7 +106,6 @@ module ActiveModel
# Accepts options that will be made available through the +options+ reader.
def initialize(options = {})
@options = options.except(:class).freeze
- deprecated_setup(options)
end
# Returns the kind for this validator.
@@ -122,21 +121,6 @@ module ActiveModel
def validate(record)
raise NotImplementedError, "Subclasses must implement a validate(record) method."
end
-
- private
- def deprecated_setup(options) # TODO: remove me in 4.2.
- return unless respond_to?(:setup)
- ActiveSupport::Deprecation.warn "The `Validator#setup` instance method is deprecated and will be removed on Rails 4.2. Do your setup in the constructor instead:
-
-class MyValidator < ActiveModel::Validator
- def initialize(options={})
- super
- options[:class].send :attr_accessor, :custom_attribute
- end
-end
-"
- setup(options[:class])
- end
end
# +EachValidator+ is a validator which iterates through the attributes given