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/callbacks.rb5
-rw-r--r--activemodel/lib/active_model/dirty.rb20
-rw-r--r--activemodel/lib/active_model/model.rb2
-rw-r--r--activemodel/lib/active_model/secure_password.rb9
-rw-r--r--activemodel/lib/active_model/serializers/json.rb2
-rw-r--r--activemodel/lib/active_model/validations.rb5
-rw-r--r--activemodel/lib/active_model/validations/acceptance.rb4
-rw-r--r--activemodel/lib/active_model/validations/confirmation.rb8
-rw-r--r--activemodel/lib/active_model/validations/with.rb3
-rw-r--r--activemodel/lib/active_model/validator.rb32
10 files changed, 59 insertions, 31 deletions
diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb
index 8b09f8b203..377aa6ee27 100644
--- a/activemodel/lib/active_model/callbacks.rb
+++ b/activemodel/lib/active_model/callbacks.rb
@@ -135,7 +135,10 @@ module ActiveModel
klass.define_singleton_method("after_#{callback}") do |*args, &block|
options = args.extract_options!
options[:prepend] = true
- options[:if] = Array(options[:if]) << "value != false"
+ conditional = ActiveSupport::Callbacks::Conditionals::Value.new { |v|
+ v != false
+ }
+ options[:if] = Array(options[:if]) << conditional
set_callback(:"#{callback}", :after, *(args << options), &block)
end
end
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index cafdb946c0..ea5ddf71de 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -142,23 +142,23 @@ module ActiveModel
@changed_attributes ||= {}
end
- private
+ # Handle <tt>*_changed?</tt> for +method_missing+.
+ def attribute_changed?(attr)
+ changed_attributes.include?(attr)
+ end
- # Handle <tt>*_changed?</tt> for +method_missing+.
- def attribute_changed?(attr)
- changed_attributes.include?(attr)
- end
+ # Handle <tt>*_was</tt> for +method_missing+.
+ def attribute_was(attr)
+ attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
+ end
+
+ private
# Handle <tt>*_change</tt> for +method_missing+.
def attribute_change(attr)
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
end
- # Handle <tt>*_was</tt> for +method_missing+.
- def attribute_was(attr)
- attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
- end
-
# Handle <tt>*_will_change!</tt> for +method_missing+.
def attribute_will_change!(attr)
return if attribute_changed?(attr)
diff --git a/activemodel/lib/active_model/model.rb b/activemodel/lib/active_model/model.rb
index 62383a03e8..f048dda5c6 100644
--- a/activemodel/lib/active_model/model.rb
+++ b/activemodel/lib/active_model/model.rb
@@ -79,6 +79,8 @@ module ActiveModel
params.each do |attr, value|
self.public_send("#{attr}=", value)
end if params
+
+ super()
end
# Indicates if the model is persisted. Default is +false+.
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb
index 750fd723a0..7156f1bb30 100644
--- a/activemodel/lib/active_model/secure_password.rb
+++ b/activemodel/lib/active_model/secure_password.rb
@@ -15,7 +15,7 @@ module ActiveModel
# argument. You can add more validations by hand if need be.
#
# If you don't need the confirmation validation, just don't set any
- # value to the password_confirmation attribute and the the validation
+ # value to the password_confirmation attribute and the validation
# will not be triggered.
#
# You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use #has_secure_password:
@@ -56,8 +56,9 @@ module ActiveModel
include InstanceMethodsOnActivation
if options.fetch(:validations, true)
- validates_confirmation_of :password
+ validates_confirmation_of :password, if: lambda { |m| m.password.present? }
validates_presence_of :password, on: :create
+ validates_presence_of :password_confirmation, if: lambda { |m| m.password.present? }
before_create { raise "Password digest missing on new record" if password_digest.blank? }
end
@@ -106,9 +107,7 @@ module ActiveModel
end
def password_confirmation=(unencrypted_password)
- unless unencrypted_password.blank?
- @password_confirmation = unencrypted_password
- end
+ @password_confirmation = unencrypted_password
end
end
end
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index 9d984b7a18..05e2e089e5 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -109,7 +109,7 @@ module ActiveModel
#
# def attributes=(hash)
# hash.each do |key, value|
- # instance_variable_set("@#{key}", value)
+ # send("#{key}=", value)
# end
# end
#
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 92206450d2..31c2245265 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -142,7 +142,9 @@ module ActiveModel
if options.key?(:on)
options = options.dup
options[:if] = Array(options[:if])
- options[:if].unshift("validation_context == :#{options[:on]}")
+ options[:if].unshift lambda { |o|
+ o.validation_context == options[:on]
+ }
end
args << options
set_callback(:validate, *args, &block)
@@ -226,7 +228,6 @@ module ActiveModel
# Person.validators_on(:name)
# # => [
# # #<ActiveModel::Validations::PresenceValidator:0x007fe604914e60 @attributes=[:name], @options={}>,
- # # #<ActiveModel::Validations::InclusionValidator:0x007fe603bb8780 @attributes=[:age], @options={in:0..99}>
# # ]
def validators_on(*attributes)
attributes.flat_map do |attribute|
diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb
index 78e6f67a47..139de16326 100644
--- a/activemodel/lib/active_model/validations/acceptance.rb
+++ b/activemodel/lib/active_model/validations/acceptance.rb
@@ -4,6 +4,7 @@ module ActiveModel
class AcceptanceValidator < EachValidator # :nodoc:
def initialize(options)
super({ allow_nil: true, accept: "1" }.merge!(options))
+ setup!(options[:class])
end
def validate_each(record, attribute, value)
@@ -12,7 +13,8 @@ module ActiveModel
end
end
- def setup(klass)
+ private
+ def setup!(klass)
attr_readers = attributes.reject { |name| klass.attribute_method?(name) }
attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
klass.send(:attr_reader, *attr_readers)
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index 1d85378892..b0542661af 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -2,6 +2,11 @@ module ActiveModel
module Validations
class ConfirmationValidator < EachValidator # :nodoc:
+ def initialize(options)
+ super
+ setup!(options[:class])
+ end
+
def validate_each(record, attribute, value)
if (confirmed = record.send("#{attribute}_confirmation")) && (value != confirmed)
human_attribute_name = record.class.human_attribute_name(attribute)
@@ -9,7 +14,8 @@ module ActiveModel
end
end
- def setup(klass)
+ private
+ def setup!(klass)
klass.send(:attr_reader, *attributes.map do |attribute|
:"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
end.compact)
diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb
index 2ae335d0f4..16bd6670d1 100644
--- a/activemodel/lib/active_model/validations/with.rb
+++ b/activemodel/lib/active_model/validations/with.rb
@@ -83,9 +83,10 @@ module ActiveModel
# end
def validates_with(*args, &block)
options = args.extract_options!
+ options[:class] = self
+
args.each do |klass|
validator = klass.new(options, &block)
- validator.setup(self) if validator.respond_to?(:setup)
if validator.respond_to?(:attributes) && !validator.attributes.empty?
validator.attributes.each do |attribute|
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index 037650e5ac..690856aee1 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -82,18 +82,16 @@ module ActiveModel
# validates :title, presence: true
# end
#
- # Validator may also define a +setup+ instance method which will get called
- # with the class that using that validator as its argument. This can be
- # useful when there are prerequisites such as an +attr_accessor+ being present.
+ # It can be useful to access the class that is using that validator when there are prerequisites such
+ # as an +attr_accessor+ being present. This class is accessable via +options[:class]+ in the constructor.
+ # To setup your validator override the constructor.
#
# class MyValidator < ActiveModel::Validator
- # def setup(klass)
- # klass.send :attr_accessor, :custom_attribute
+ # def initialize(options={})
+ # super
+ # options[:class].send :attr_accessor, :custom_attribute
# end
# end
- #
- # This setup method is only called when used with validation macros or the
- # class level <tt>validates_with</tt> method.
class Validator
attr_reader :options
@@ -107,7 +105,8 @@ module ActiveModel
# Accepts options that will be made available through the +options+ reader.
def initialize(options = {})
- @options = options.freeze
+ @options = options.except(:class).freeze
+ deprecated_setup(options)
end
# Return the kind for this validator.
@@ -123,6 +122,21 @@ 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