diff options
Diffstat (limited to 'activemodel')
112 files changed, 1516 insertions, 1630 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 206699c036..853a1e7d9d 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,2 +1,22 @@ +* Moved DecimalWithoutScale, Text, and UnsignedInteger from Active Model to Active Record + + *Iain Beeston* + +* Allow indifferent access in `ActiveModel::Errors`. + + `#include?`, `#has_key?`, `#key?`, `#delete` and `#full_messages_for`. + + *Kenichi Kamiya* + +* Removed deprecated `:tokenizer` in the length validator. + + *Rafael Mendonça França* + +* Removed deprecated methods in `ActiveModel::Errors`. + + `#get`, `#set`, `[]=`, `add_on_empty` and `add_on_blank`. + + *Rafael Mendonça França* + Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/activemodel/CHANGELOG.md) for previous changes. diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE index 8573eb1225..ac810e86d0 100644 --- a/activemodel/MIT-LICENSE +++ b/activemodel/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2016 David Heinemeier Hansson +Copyright (c) 2004-2017 David Heinemeier Hansson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/activemodel/Rakefile b/activemodel/Rakefile index 036815a987..c7f97a4258 100644 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -1,8 +1,8 @@ -require 'rake/testtask' +require "rake/testtask" dir = File.dirname(__FILE__) -task :default => :test +task default: :test task :package @@ -17,7 +17,7 @@ end namespace :test do task :isolated do Dir.glob("#{dir}/test/**/*_test.rb").all? do |file| - sh(Gem.ruby, '-w', "-I#{dir}/lib", "-I#{dir}/test", file) - end or raise "Failures" + sh(Gem.ruby, "-w", "-I#{dir}/lib", "-I#{dir}/test", file) + end || raise("Failures") end end diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index 1c3997b864..fd715f6ba9 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -1,22 +1,22 @@ -version = File.read(File.expand_path('../../RAILS_VERSION', __FILE__)).strip +version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY - s.name = 'activemodel' + s.name = "activemodel" s.version = version - s.summary = 'A toolkit for building modeling frameworks (part of Rails).' - s.description = 'A toolkit for building modeling frameworks like Active Record. Rich support for attributes, callbacks, validations, serialization, internationalization, and testing.' + s.summary = "A toolkit for building modeling frameworks (part of Rails)." + s.description = "A toolkit for building modeling frameworks like Active Record. Rich support for attributes, callbacks, validations, serialization, internationalization, and testing." - s.required_ruby_version = '>= 2.2.2' + s.required_ruby_version = ">= 2.2.2" - s.license = 'MIT' + s.license = "MIT" - s.author = 'David Heinemeier Hansson' - s.email = 'david@loudthinking.com' - s.homepage = 'http://rubyonrails.org' + s.author = "David Heinemeier Hansson" + s.email = "david@loudthinking.com" + s.homepage = "http://rubyonrails.org" - s.files = Dir['CHANGELOG.md', 'MIT-LICENSE', 'README.rdoc', 'lib/**/*'] - s.require_path = 'lib' + s.files = Dir["CHANGELOG.md", "MIT-LICENSE", "README.rdoc", "lib/**/*"] + s.require_path = "lib" - s.add_dependency 'activesupport', version + s.add_dependency "activesupport", version end diff --git a/activemodel/bin/test b/activemodel/bin/test index 404cabba51..a7beb14b27 100755 --- a/activemodel/bin/test +++ b/activemodel/bin/test @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -COMPONENT_ROOT = File.expand_path("../../", __FILE__) + +COMPONENT_ROOT = File.expand_path("..", __dir__) require File.expand_path("../tools/test", COMPONENT_ROOT) -exit Minitest.run(ARGV) diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index 7de259a60d..8163856a46 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2004-2016 David Heinemeier Hansson +# Copyright (c) 2004-2017 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,24 +21,24 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -require 'active_support' -require 'active_support/rails' -require 'active_model/version' +require "active_support" +require "active_support/rails" +require "active_model/version" module ActiveModel extend ActiveSupport::Autoload autoload :AttributeAssignment autoload :AttributeMethods - autoload :BlockValidator, 'active_model/validator' + autoload :BlockValidator, "active_model/validator" autoload :Callbacks autoload :Conversion autoload :Dirty - autoload :EachValidator, 'active_model/validator' + autoload :EachValidator, "active_model/validator" autoload :ForbiddenAttributesProtection autoload :Lint autoload :Model - autoload :Name, 'active_model/naming' + autoload :Name, "active_model/naming" autoload :Naming autoload :SecurePassword autoload :Serialization @@ -49,9 +49,9 @@ module ActiveModel eager_autoload do autoload :Errors - autoload :RangeError, 'active_model/errors' - autoload :StrictValidationFailed, 'active_model/errors' - autoload :UnknownAttributeError, 'active_model/errors' + autoload :RangeError, "active_model/errors" + autoload :StrictValidationFailed, "active_model/errors" + autoload :UnknownAttributeError, "active_model/errors" end module Serializers @@ -69,5 +69,5 @@ module ActiveModel end ActiveSupport.on_load(:i18n) do - I18n.load_path << File.dirname(__FILE__) + '/active_model/locale/en.yml' + I18n.load_path << File.dirname(__FILE__) + "/active_model/locale/en.yml" end diff --git a/activemodel/lib/active_model/attribute_assignment.rb b/activemodel/lib/active_model/attribute_assignment.rb index 62014cd1cd..7dad3b6dff 100644 --- a/activemodel/lib/active_model/attribute_assignment.rb +++ b/activemodel/lib/active_model/attribute_assignment.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/hash/keys' +require "active_support/core_ext/hash/keys" module ActiveModel module AttributeAssignment @@ -35,18 +35,18 @@ module ActiveModel private - def _assign_attributes(attributes) - attributes.each do |k, v| - _assign_attribute(k, v) + def _assign_attributes(attributes) + attributes.each do |k, v| + _assign_attribute(k, v) + end end - end - def _assign_attribute(k, v) - if respond_to?("#{k}=") - public_send("#{k}=", v) - else - raise UnknownAttributeError.new(self, k) + def _assign_attribute(k, v) + if respond_to?("#{k}=") + public_send("#{k}=", v) + else + raise UnknownAttributeError.new(self, k) + end end - end end end diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index cc6285f932..09825cf861 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -1,5 +1,5 @@ -require 'concurrent/map' -require 'mutex_m' +require "concurrent/map" +require "mutex_m" module ActiveModel # Raised when an attribute is not defined. @@ -334,12 +334,11 @@ module ActiveModel }.tap { |mod| include mod } end - protected - def instance_method_already_implemented?(method_name) #:nodoc: + private + def instance_method_already_implemented?(method_name) generated_attribute_methods.method_defined?(method_name) end - private # The methods +method_missing+ and +respond_to?+ of this module are # invoked often in a typical rails, both of which invoke the method # +matched_attribute_method+. The latter method iterates through an @@ -349,11 +348,11 @@ module ActiveModel # used to alleviate the GC, which ultimately also speeds up the app # significantly (in our case our test suite finishes 10% faster with # this cache). - def attribute_method_matchers_cache #:nodoc: + def attribute_method_matchers_cache @attribute_method_matchers_cache ||= Concurrent::Map.new(initial_capacity: 4) end - def attribute_method_matchers_matching(method_name) #:nodoc: + def attribute_method_matchers_matching(method_name) attribute_method_matchers_cache.compute_if_absent(method_name) do # Must try to match prefixes/suffixes first, or else the matcher with no prefix/suffix # will match every time. @@ -365,8 +364,8 @@ module ActiveModel # Define a method `name` in `mod` that dispatches to `send` # using the given `extra` args. This falls back on `define_method` # and `send` if the given names cannot be compiled. - def define_proxy_call(include_private, mod, name, send, *extra) #:nodoc: - defn = if name =~ NAME_COMPILABLE_REGEXP + def define_proxy_call(include_private, mod, name, send, *extra) + defn = if NAME_COMPILABLE_REGEXP.match?(name) "def #{name}(*args)" else "define_method(:'#{name}') do |*args|" @@ -374,7 +373,7 @@ module ActiveModel extra = (extra.map!(&:inspect) << "*args").join(", ".freeze) - target = if send =~ CALL_COMPILABLE_REGEXP + target = if CALL_COMPILABLE_REGEXP.match?(send) "#{"self." unless include_private}#{send}(#{extra})" else "send(:'#{send}', #{extra})" @@ -393,7 +392,7 @@ module ActiveModel AttributeMethodMatch = Struct.new(:target, :attr_name, :method_name) def initialize(options = {}) - @prefix, @suffix = options.fetch(:prefix, ''), options.fetch(:suffix, '') + @prefix, @suffix = options.fetch(:prefix, ""), options.fetch(:suffix, "") @regex = /^(?:#{Regexp.escape(@prefix)})(.*)(?:#{Regexp.escape(@suffix)})$/ @method_missing_target = "#{@prefix}attribute#{@suffix}" @method_name = "#{prefix}%s#{suffix}" @@ -458,12 +457,11 @@ module ActiveModel end end - protected - def attribute_method?(attr_name) #:nodoc: + private + def attribute_method?(attr_name) respond_to_without_attributes?(:attributes) && attributes.include?(attr_name) end - private # Returns a struct representing the matching attribute method. # The struct's attributes are prefix, base and suffix. def matched_attribute_method(method_name) diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index 0d6a3dc52d..e99bfab6fd 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/array/extract_options' +require "active_support/core_ext/array/extract_options" module ActiveModel # == Active \Model \Callbacks @@ -122,28 +122,28 @@ module ActiveModel private - def _define_before_model_callback(klass, callback) #:nodoc: - klass.define_singleton_method("before_#{callback}") do |*args, &block| - set_callback(:"#{callback}", :before, *args, &block) + def _define_before_model_callback(klass, callback) + klass.define_singleton_method("before_#{callback}") do |*args, &block| + set_callback(:"#{callback}", :before, *args, &block) + end end - end - def _define_around_model_callback(klass, callback) #:nodoc: - klass.define_singleton_method("around_#{callback}") do |*args, &block| - set_callback(:"#{callback}", :around, *args, &block) + def _define_around_model_callback(klass, callback) + klass.define_singleton_method("around_#{callback}") do |*args, &block| + set_callback(:"#{callback}", :around, *args, &block) + end end - end - def _define_after_model_callback(klass, callback) #:nodoc: - klass.define_singleton_method("after_#{callback}") do |*args, &block| - options = args.extract_options! - options[:prepend] = true - conditional = ActiveSupport::Callbacks::Conditionals::Value.new { |v| - v != false - } - options[:if] = Array(options[:if]) << conditional - set_callback(:"#{callback}", :after, *(args << options), &block) + def _define_after_model_callback(klass, callback) + klass.define_singleton_method("after_#{callback}") do |*args, &block| + options = args.extract_options! + options[:prepend] = true + conditional = ActiveSupport::Callbacks::Conditionals::Value.new { |v| + v != false + } + options[:if] = Array(options[:if]) << conditional + set_callback(:"#{callback}", :after, *(args << options), &block) + end end - end end end diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb index a932ada45c..12687c70d3 100644 --- a/activemodel/lib/active_model/conversion.rb +++ b/activemodel/lib/active_model/conversion.rb @@ -46,9 +46,13 @@ module ActiveModel # class Person # include ActiveModel::Conversion # attr_accessor :id + # + # def initialize(id) + # @id = id + # end # end # - # person = Person.create(id: 1) + # person = Person.new(1) # person.to_key # => [1] def to_key key = respond_to?(:id) && id @@ -61,15 +65,20 @@ module ActiveModel # class Person # include ActiveModel::Conversion # attr_accessor :id + # + # def initialize(id) + # @id = id + # end + # # def persisted? # true # end # end # - # person = Person.create(id: 1) + # person = Person.new(1) # person.to_param # => "1" def to_param - (persisted? && key = to_key) ? key.join('-') : nil + (persisted? && key = to_key) ? key.join("-") : nil end # Returns a +string+ identifying the path associated with the object. diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index 90047c3c12..6e0af99ad7 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -1,5 +1,5 @@ -require 'active_support/hash_with_indifferent_access' -require 'active_support/core_ext/object/duplicable' +require "active_support/hash_with_indifferent_access" +require "active_support/core_ext/object/duplicable" module ActiveModel # == Active \Model \Dirty @@ -26,8 +26,8 @@ module ActiveModel # # define_attribute_methods :name # - # def initialize(name) - # @name = name + # def initialize + # @name = nil # end # # def name @@ -58,7 +58,7 @@ module ActiveModel # # A newly instantiated +Person+ object is unchanged: # - # person = Person.new("Uncle Bob") + # person = Person.new # person.changed? # => false # # Change the name: @@ -66,11 +66,11 @@ module ActiveModel # person.name = 'Bob' # person.changed? # => true # person.name_changed? # => true - # person.name_changed?(from: "Uncle Bob", to: "Bob") # => true - # person.name_was # => "Uncle Bob" - # person.name_change # => ["Uncle Bob", "Bob"] + # person.name_changed?(from: nil, to: "Bob") # => true + # person.name_was # => nil + # person.name_change # => [nil, "Bob"] # person.name = 'Bill' - # person.name_change # => ["Uncle Bob", "Bill"] + # person.name_change # => [nil, "Bill"] # # Save the changes: # @@ -80,9 +80,9 @@ module ActiveModel # # Reset the changes: # - # person.previous_changes # => {"name" => ["Uncle Bob", "Bill"]} + # person.previous_changes # => {"name" => [nil, "Bill"]} # person.name_previously_changed? # => true - # person.name_previous_change # => ["Uncle Bob", "Bill"] + # person.name_previous_change # => [nil, "Bill"] # person.reload! # person.previous_changes # => {} # @@ -123,9 +123,9 @@ module ActiveModel private_constant :OPTION_NOT_GIVEN included do - attribute_method_suffix '_changed?', '_change', '_will_change!', '_was' - attribute_method_suffix '_previously_changed?', '_previous_change' - attribute_method_affix prefix: 'restore_', suffix: '!' + attribute_method_suffix "_changed?", "_change", "_will_change!", "_was" + attribute_method_suffix "_previously_changed?", "_previous_change" + attribute_method_affix prefix: "restore_", suffix: "!" end # Returns +true+ if any of the attributes have unsaved changes, +false+ otherwise. diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 6f2c8c1c53..9df4ca51fe 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -1,7 +1,7 @@ -require 'active_support/core_ext/array/conversions' -require 'active_support/core_ext/string/inflections' -require 'active_support/core_ext/object/deep_dup' -require 'active_support/core_ext/string/filters' +require "active_support/core_ext/array/conversions" +require "active_support/core_ext/string/inflections" +require "active_support/core_ext/object/deep_dup" +require "active_support/core_ext/string/filters" module ActiveModel # == Active \Model \Errors @@ -110,49 +110,21 @@ module ActiveModel # person.errors.include?(:name) # => true # person.errors.include?(:age) # => false def include?(attribute) + attribute = attribute.to_sym messages.key?(attribute) && messages[attribute].present? end alias :has_key? :include? alias :key? :include? - # Get messages for +key+. - # - # person.errors.messages # => {:name=>["cannot be nil"]} - # person.errors.get(:name) # => ["cannot be nil"] - # person.errors.get(:age) # => [] - def get(key) - ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) - ActiveModel::Errors#get is deprecated and will be removed in Rails 5.1. - - To achieve the same use model.errors[:#{key}]. - MESSAGE - - messages[key] - end - - # Set messages for +key+ to +value+. - # - # person.errors[:name] # => ["cannot be nil"] - # person.errors.set(:name, ["can't be nil"]) - # person.errors[:name] # => ["can't be nil"] - def set(key, value) - ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) - ActiveModel::Errors#set is deprecated and will be removed in Rails 5.1. - - Use model.errors.add(:#{key}, #{value.inspect}) instead. - MESSAGE - - messages[key] = value - end - # Delete messages for +key+. Returns the deleted messages. # - # person.errors[:name] # => ["cannot be nil"] + # person.errors[:name] # => ["cannot be nil"] # person.errors.delete(:name) # => ["cannot be nil"] - # person.errors[:name] # => [] + # person.errors[:name] # => [] def delete(key) - details.delete(key) - messages.delete(key) + attribute = key.to_sym + details.delete(attribute) + messages.delete(attribute) end # When passed a symbol or a name of a method, returns an array of errors @@ -173,20 +145,6 @@ module ActiveModel messages[attribute.to_sym] end - # Adds to the supplied attribute the supplied error message. - # - # person.errors[:name] = "must be set" - # person.errors[:name] # => ['must be set'] - def []=(attribute, error) - ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) - ActiveModel::Errors#[]= is deprecated and will be removed in Rails 5.1. - - Use model.errors.add(:#{attribute}, #{error.inspect}) instead. - MESSAGE - - messages[attribute.to_sym] << error - end - # Iterates through each error key, value pair in the error messages hash. # Yields the attribute and the error for that attribute. If the attribute # has more than one error message, yields once for each error message. @@ -255,7 +213,7 @@ module ActiveModel # # <error>name can't be blank</error> # # <error>name must be specified</error> # # </errors> - def to_xml(options={}) + def to_xml(options = {}) to_a.to_xml({ root: "errors", skip_types: true }.merge!(options)) end @@ -265,7 +223,7 @@ module ActiveModel # # person.errors.as_json # => {:name=>["cannot be nil"]} # person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]} - def as_json(options=nil) + def as_json(options = nil) to_hash(options && options[:full_messages]) end @@ -276,11 +234,11 @@ module ActiveModel # person.errors.to_hash(true) # => {:name=>["name cannot be nil"]} def to_hash(full_messages = false) if full_messages - self.messages.each_with_object({}) do |(attribute, array), messages| + messages.each_with_object({}) do |(attribute, array), messages| messages[attribute] = array.map { |message| full_message(attribute, message) } end else - self.messages.dup + without_default_proc(messages) end end @@ -338,54 +296,22 @@ module ActiveModel messages[attribute.to_sym] << message end - # Will add an error message to each of the attributes in +attributes+ - # that is empty. - # - # person.errors.add_on_empty(:name) - # person.errors.messages - # # => {:name=>["can't be empty"]} - def add_on_empty(attributes, options = {}) - ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) - ActiveModel::Errors#add_on_empty is deprecated and will be removed in Rails 5.1. - - To achieve the same use: - - errors.add(attribute, :empty, options) if value.nil? || value.empty? - MESSAGE - - Array(attributes).each do |attribute| - value = @base.send(:read_attribute_for_validation, attribute) - is_empty = value.respond_to?(:empty?) ? value.empty? : false - add(attribute, :empty, options) if value.nil? || is_empty - end - end - - # Will add an error message to each of the attributes in +attributes+ that - # is blank (using Object#blank?). - # - # person.errors.add_on_blank(:name) - # person.errors.messages - # # => {:name=>["can't be blank"]} - def add_on_blank(attributes, options = {}) - ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) - ActiveModel::Errors#add_on_blank is deprecated and will be removed in Rails 5.1. - - To achieve the same use: - - errors.add(attribute, :empty, options) if value.blank? - MESSAGE - - Array(attributes).each do |attribute| - value = @base.send(:read_attribute_for_validation, attribute) - add(attribute, :blank, options) if value.blank? - end - end - # Returns +true+ if an error on the attribute with the given message is - # present, +false+ otherwise. +message+ is treated the same as for +add+. + # present, or +false+ otherwise. +message+ is treated the same as for +add+. # # person.errors.add :name, :blank - # person.errors.added? :name, :blank # => true + # person.errors.added? :name, :blank # => true + # person.errors.added? :name, "can't be blank" # => true + # + # If the error message requires an option, then it returns +true+ with + # the correct option, or +false+ with an incorrect or missing option. + # + # person.errors.add :name, :too_long, { count: 25 } + # person.errors.added? :name, :too_long, count: 25 # => true + # person.errors.added? :name, "is too long (maximum is 25 characters)" # => true + # person.errors.added? :name, :too_long, count: 24 # => false + # person.errors.added? :name, :too_long # => false + # person.errors.added? :name, "is too long" # => false def added?(attribute, message = :invalid, options = {}) message = message.call if message.respond_to?(:call) message = normalize_message(attribute, message, options) @@ -418,6 +344,7 @@ module ActiveModel # person.errors.full_messages_for(:name) # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"] def full_messages_for(attribute) + attribute = attribute.to_sym messages[attribute].map { |message| full_message(attribute, message) } end @@ -426,13 +353,12 @@ module ActiveModel # person.errors.full_message(:name, 'is invalid') # => "Name is invalid" def full_message(attribute, message) return message if attribute == :base - attr_name = attribute.to_s.tr('.', '_').humanize + attr_name = attribute.to_s.tr(".", "_").humanize attr_name = @base.class.human_attribute_name(attribute, default: attr_name) - I18n.t(:"errors.format", { + I18n.t(:"errors.format", default: "%{attribute} %{message}", attribute: attr_name, - message: message - }) + message: message) end # Translates an error message in its default scope @@ -493,16 +419,23 @@ module ActiveModel I18n.translate(key, options) end - def marshal_dump + def marshal_dump # :nodoc: [@base, without_default_proc(@messages), without_default_proc(@details)] end - def marshal_load(array) + def marshal_load(array) # :nodoc: @base, @messages, @details = array apply_default_array(@messages) apply_default_array(@details) end + def init_with(coder) # :nodoc: + coder.map.each { |k, v| instance_variable_set(:"@#{k}", v) } + @details ||= {} + apply_default_array(@messages) + apply_default_array(@details) + end + private def normalize_message(attribute, message, options) case message diff --git a/activemodel/lib/active_model/forbidden_attributes_protection.rb b/activemodel/lib/active_model/forbidden_attributes_protection.rb index d2c6a89cc2..45ab8a2ca1 100644 --- a/activemodel/lib/active_model/forbidden_attributes_protection.rb +++ b/activemodel/lib/active_model/forbidden_attributes_protection.rb @@ -15,7 +15,7 @@ module ActiveModel end module ForbiddenAttributesProtection # :nodoc: - protected + private def sanitize_for_mass_assignment(attributes) if attributes.respond_to?(:permitted?) raise ActiveModel::ForbiddenAttributesError if !attributes.permitted? diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb index 010eaeb170..291a545528 100644 --- a/activemodel/lib/active_model/lint.rb +++ b/activemodel/lib/active_model/lint.rb @@ -20,7 +20,6 @@ module ActiveModel # to <tt>to_model</tt>. It is perfectly fine for <tt>to_model</tt> to return # +self+. module Tests - # Passes if the object's model responds to <tt>to_key</tt> and if calling # this method returns +nil+ when the object is not persisted. # Fails otherwise. diff --git a/activemodel/lib/active_model/model.rb b/activemodel/lib/active_model/model.rb index dac8d549a7..945a5402a3 100644 --- a/activemodel/lib/active_model/model.rb +++ b/activemodel/lib/active_model/model.rb @@ -1,12 +1,11 @@ module ActiveModel - # == Active \Model \Basic \Model # # Includes the required interface for an object to interact with - # <tt>ActionPack</tt>, using different <tt>ActiveModel</tt> modules. + # Action Pack and Action View, using different Active Model modules. # It includes model name introspections, conversions, translations and # validations. Besides that, it allows you to initialize the object with a - # hash of attributes, pretty much like <tt>ActiveRecord</tt> does. + # hash of attributes, pretty much like Active Record does. # # A minimal implementation could be: # @@ -76,7 +75,7 @@ module ActiveModel # person = Person.new(name: 'bob', age: '18') # person.name # => "bob" # person.age # => "18" - def initialize(attributes={}) + def initialize(attributes = {}) assign_attributes(attributes) if attributes super() diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index d86ef6224e..9532c63b65 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -1,7 +1,6 @@ -require 'active_support/core_ext/hash/except' -require 'active_support/core_ext/module/introspection' -require 'active_support/core_ext/module/remove_method' -require 'active_support/core_ext/module/delegation' +require "active_support/core_ext/hash/except" +require "active_support/core_ext/module/introspection" +require "active_support/core_ext/module/remove_method" module ActiveModel class Name @@ -149,7 +148,7 @@ module ActiveModel raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if @name.blank? - @unnamespaced = @name.sub(/^#{namespace.name}::/, '') if namespace + @unnamespaced = @name.sub(/^#{namespace.name}::/, "") if namespace @klass = klass @singular = _singularize(@name) @plural = ActiveSupport::Inflector.pluralize(@singular) @@ -174,7 +173,7 @@ module ActiveModel # BlogPost.model_name.human # => "Blog post" # # Specify +options+ with additional translating options. - def human(options={}) + def human(options = {}) return @human unless @klass.respond_to?(:lookup_ancestors) && @klass.respond_to?(:i18n_scope) @@ -191,9 +190,9 @@ module ActiveModel private - def _singularize(string) - ActiveSupport::Inflector.underscore(string).tr('/'.freeze, '_'.freeze) - end + def _singularize(string) + ActiveSupport::Inflector.underscore(string).tr("/".freeze, "_".freeze) + end end # == Active \Model \Naming diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 89da74efa8..1c0fe92bc0 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -55,7 +55,7 @@ module ActiveModel # This is to avoid ActiveModel (and by extension the entire framework) # being dependent on a binary library. begin - require 'bcrypt' + require "bcrypt" rescue LoadError $stderr.puts "You don't have bcrypt installed in your application. Please add it to your Gemfile and run bundle install" raise diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index 70e10fa06d..77834f26fc 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -1,5 +1,5 @@ -require 'active_support/core_ext/hash/except' -require 'active_support/core_ext/hash/slice' +require "active_support/core_ext/hash/except" +require "active_support/core_ext/hash/slice" module ActiveModel # == Active \Model \Serialization diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb index b64a8299e6..a9d92eb92a 100644 --- a/activemodel/lib/active_model/serializers/json.rb +++ b/activemodel/lib/active_model/serializers/json.rb @@ -1,4 +1,4 @@ -require 'active_support/json' +require "active_support/json" module ActiveModel module Serializers @@ -134,7 +134,7 @@ module ActiveModel # person.name # => "bob" # person.age # => 22 # person.awesome # => true - def from_json(json, include_root=include_root_in_json) + def from_json(json, include_root = include_root_in_json) hash = ActiveSupport::JSON.decode(json) hash = hash.values.first if include_root self.attributes = hash diff --git a/activemodel/lib/active_model/translation.rb b/activemodel/lib/active_model/translation.rb index 8470915abb..b8cf43cc10 100644 --- a/activemodel/lib/active_model/translation.rb +++ b/activemodel/lib/active_model/translation.rb @@ -1,5 +1,4 @@ module ActiveModel - # == Active \Model \Translation # # Provides integration between your object and the Rails internationalization @@ -31,7 +30,7 @@ module ActiveModel # ActiveModel::Errors#full_messages and # ActiveModel::Translation#human_attribute_name. def lookup_ancestors - self.ancestors.select { |x| x.respond_to?(:model_name) } + ancestors.select { |x| x.respond_to?(:model_name) } end # Transforms attribute names into a more human format, such as "First name" diff --git a/activemodel/lib/active_model/type.rb b/activemodel/lib/active_model/type.rb index 6ec3452478..b8e6d2376b 100644 --- a/activemodel/lib/active_model/type.rb +++ b/activemodel/lib/active_model/type.rb @@ -1,22 +1,19 @@ -require 'active_model/type/helpers' -require 'active_model/type/value' +require "active_model/type/helpers" +require "active_model/type/value" -require 'active_model/type/big_integer' -require 'active_model/type/binary' -require 'active_model/type/boolean' -require 'active_model/type/date' -require 'active_model/type/date_time' -require 'active_model/type/decimal' -require 'active_model/type/decimal_without_scale' -require 'active_model/type/float' -require 'active_model/type/immutable_string' -require 'active_model/type/integer' -require 'active_model/type/string' -require 'active_model/type/text' -require 'active_model/type/time' -require 'active_model/type/unsigned_integer' +require "active_model/type/big_integer" +require "active_model/type/binary" +require "active_model/type/boolean" +require "active_model/type/date" +require "active_model/type/date_time" +require "active_model/type/decimal" +require "active_model/type/float" +require "active_model/type/immutable_string" +require "active_model/type/integer" +require "active_model/type/string" +require "active_model/type/time" -require 'active_model/type/registry' +require "active_model/type/registry" module ActiveModel module Type @@ -27,7 +24,7 @@ module ActiveModel delegate :add_modifier, to: :registry # Add a new type to the registry, allowing it to be referenced as a - # symbol by ActiveModel::Attributes::ClassMethods#attribute. If your + # symbol by ActiveRecord::Attributes::ClassMethods#attribute. If your # type is only meant to be used with a specific database adapter, you can # do so by passing +adapter: :postgresql+. If your type has the same # name as a native type for the current adapter, an exception will be @@ -53,7 +50,6 @@ module ActiveModel register(:immutable_string, Type::ImmutableString) register(:integer, Type::Integer) register(:string, Type::String) - register(:text, Type::Text) register(:time, Type::Time) end end diff --git a/activemodel/lib/active_model/type/big_integer.rb b/activemodel/lib/active_model/type/big_integer.rb index 4168cbfce7..3b629682fe 100644 --- a/activemodel/lib/active_model/type/big_integer.rb +++ b/activemodel/lib/active_model/type/big_integer.rb @@ -1,13 +1,13 @@ -require 'active_model/type/integer' +require "active_model/type/integer" module ActiveModel module Type class BigInteger < Integer # :nodoc: private - def max_value - ::Float::INFINITY - end + def max_value + ::Float::INFINITY + end end end end diff --git a/activemodel/lib/active_model/type/binary.rb b/activemodel/lib/active_model/type/binary.rb index a0cc45b4c3..819e4e4a96 100644 --- a/activemodel/lib/active_model/type/binary.rb +++ b/activemodel/lib/active_model/type/binary.rb @@ -38,7 +38,7 @@ module ActiveModel alias_method :to_str, :to_s def hex - @value.unpack('H*')[0] + @value.unpack("H*")[0] end def ==(other) diff --git a/activemodel/lib/active_model/type/boolean.rb b/activemodel/lib/active_model/type/boolean.rb index c1bce98c87..f2a47370a3 100644 --- a/activemodel/lib/active_model/type/boolean.rb +++ b/activemodel/lib/active_model/type/boolean.rb @@ -1,21 +1,32 @@ module ActiveModel module Type - class Boolean < Value # :nodoc: - FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set + # == Active \Model \Type \Boolean + # + # A class that behaves like a boolean type, including rules for coercion of user input. + # + # === Coercion + # Values set from user input will first be coerced into the appropriate ruby type. + # Coercion behavior is roughly mapped to Ruby's boolean semantics. + # + # - "false", "f" , "0", +0+ or any other value in +FALSE_VALUES+ will be coerced to +false+ + # - Empty strings are coerced to +nil+ + # - All other values will be coerced to +true+ + class Boolean < Value + FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"].to_set - def type + def type # :nodoc: :boolean end private - def cast_value(value) - if value == '' - nil - else - !FALSE_VALUES.include?(value) + def cast_value(value) + if value == "" + nil + else + !FALSE_VALUES.include?(value) + end end - end end end end diff --git a/activemodel/lib/active_model/type/date.rb b/activemodel/lib/active_model/type/date.rb index f74243a22c..6e313fbca8 100644 --- a/activemodel/lib/active_model/type/date.rb +++ b/activemodel/lib/active_model/type/date.rb @@ -7,44 +7,48 @@ module ActiveModel :date end + def serialize(value) + cast(value) + end + def type_cast_for_schema(value) "'#{value.to_s(:db)}'" end private - def cast_value(value) - if value.is_a?(::String) - return if value.empty? - fast_string_to_date(value) || fallback_string_to_date(value) - elsif value.respond_to?(:to_date) - value.to_date - else - value + def cast_value(value) + if value.is_a?(::String) + return if value.empty? + fast_string_to_date(value) || fallback_string_to_date(value) + elsif value.respond_to?(:to_date) + value.to_date + else + value + end end - end - ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ - def fast_string_to_date(string) - if string =~ ISO_DATE - new_date $1.to_i, $2.to_i, $3.to_i + ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ + def fast_string_to_date(string) + if string =~ ISO_DATE + new_date $1.to_i, $2.to_i, $3.to_i + end end - end - def fallback_string_to_date(string) - new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday)) - end + def fallback_string_to_date(string) + new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday)) + end - def new_date(year, mon, mday) - if year && year != 0 - ::Date.new(year, mon, mday) rescue nil + def new_date(year, mon, mday) + if year && year != 0 + ::Date.new(year, mon, mday) rescue nil + end end - end - def value_from_multiparameter_assignment(*) - time = super - time && time.to_date - end + def value_from_multiparameter_assignment(*) + time = super + time && time.to_date + end end end end diff --git a/activemodel/lib/active_model/type/date_time.rb b/activemodel/lib/active_model/type/date_time.rb index 2f2df4320f..5cb0077e45 100644 --- a/activemodel/lib/active_model/type/date_time.rb +++ b/activemodel/lib/active_model/type/date_time.rb @@ -12,33 +12,33 @@ module ActiveModel private - def cast_value(value) - return apply_seconds_precision(value) unless value.is_a?(::String) - return if value.empty? + def cast_value(value) + return apply_seconds_precision(value) unless value.is_a?(::String) + return if value.empty? - fast_string_to_time(value) || fallback_string_to_time(value) - end + fast_string_to_time(value) || fallback_string_to_time(value) + end - # '0.123456' -> 123456 - # '1.123456' -> 123456 - def microseconds(time) - time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0 - end + # '0.123456' -> 123456 + # '1.123456' -> 123456 + def microseconds(time) + time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0 + end - def fallback_string_to_time(string) - time_hash = ::Date._parse(string) - time_hash[:sec_fraction] = microseconds(time_hash) + def fallback_string_to_time(string) + time_hash = ::Date._parse(string) + time_hash[:sec_fraction] = microseconds(time_hash) - new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) - end + new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) + end - def value_from_multiparameter_assignment(values_hash) - missing_parameter = (1..3).detect { |key| !values_hash.key?(key) } - if missing_parameter - raise ArgumentError, missing_parameter + def value_from_multiparameter_assignment(values_hash) + missing_parameter = (1..3).detect { |key| !values_hash.key?(key) } + if missing_parameter + raise ArgumentError, missing_parameter + end + super end - super - end end end end diff --git a/activemodel/lib/active_model/type/decimal.rb b/activemodel/lib/active_model/type/decimal.rb index 11ea327026..6c5c0451c6 100644 --- a/activemodel/lib/active_model/type/decimal.rb +++ b/activemodel/lib/active_model/type/decimal.rb @@ -15,46 +15,47 @@ module ActiveModel private - def cast_value(value) - casted_value = case value - when ::Float - convert_float_to_big_decimal(value) - when ::Numeric, ::String - BigDecimal(value, precision.to_i) - else - if value.respond_to?(:to_d) - value.to_d + def cast_value(value) + casted_value = \ + case value + when ::Float + convert_float_to_big_decimal(value) + when ::Numeric, ::String + BigDecimal(value, precision.to_i) + else + if value.respond_to?(:to_d) + value.to_d + else + cast_value(value.to_s) + end + end + + apply_scale(casted_value) + end + + def convert_float_to_big_decimal(value) + if precision + BigDecimal(apply_scale(value), float_precision) else - cast_value(value.to_s) + value.to_d end end - apply_scale(casted_value) - end - - def convert_float_to_big_decimal(value) - if precision - BigDecimal(apply_scale(value), float_precision) - else - value.to_d - end - end - - def float_precision - if precision.to_i > ::Float::DIG + 1 - ::Float::DIG + 1 - else - precision.to_i + def float_precision + if precision.to_i > ::Float::DIG + 1 + ::Float::DIG + 1 + else + precision.to_i + end end - end - def apply_scale(value) - if scale - value.round(scale) - else - value + def apply_scale(value) + if scale + value.round(scale) + else + value + end end - end end end end diff --git a/activemodel/lib/active_model/type/decimal_without_scale.rb b/activemodel/lib/active_model/type/decimal_without_scale.rb deleted file mode 100644 index 129baa0c10..0000000000 --- a/activemodel/lib/active_model/type/decimal_without_scale.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'active_model/type/big_integer' - -module ActiveModel - module Type - class DecimalWithoutScale < BigInteger # :nodoc: - def type - :decimal - end - end - end -end diff --git a/activemodel/lib/active_model/type/float.rb b/activemodel/lib/active_model/type/float.rb index 0f925bc7e1..4d0d2771a0 100644 --- a/activemodel/lib/active_model/type/float.rb +++ b/activemodel/lib/active_model/type/float.rb @@ -7,19 +7,28 @@ module ActiveModel :float end + def type_cast_for_schema(value) + return "::Float::NAN" if value.try(:nan?) + case value + when ::Float::INFINITY then "::Float::INFINITY" + when -::Float::INFINITY then "-::Float::INFINITY" + else super + end + end + alias serialize cast private - def cast_value(value) - case value - when ::Float then value - when "Infinity" then ::Float::INFINITY - when "-Infinity" then -::Float::INFINITY - when "NaN" then ::Float::NAN - else value.to_f + def cast_value(value) + case value + when ::Float then value + when "Infinity" then ::Float::INFINITY + when "-Infinity" then -::Float::INFINITY + when "NaN" then ::Float::NAN + else value.to_f + end end - end end end end diff --git a/activemodel/lib/active_model/type/helpers.rb b/activemodel/lib/active_model/type/helpers.rb index a805a359ab..82cd9ebe98 100644 --- a/activemodel/lib/active_model/type/helpers.rb +++ b/activemodel/lib/active_model/type/helpers.rb @@ -1,4 +1,4 @@ -require 'active_model/type/helpers/accepts_multiparameter_time' -require 'active_model/type/helpers/numeric' -require 'active_model/type/helpers/mutable' -require 'active_model/type/helpers/time_value' +require "active_model/type/helpers/accepts_multiparameter_time" +require "active_model/type/helpers/numeric" +require "active_model/type/helpers/mutable" +require "active_model/type/helpers/time_value" diff --git a/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb b/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb index facea12704..f783d286c5 100644 --- a/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb +++ b/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb @@ -1,7 +1,7 @@ module ActiveModel module Type - module Helpers - class AcceptsMultiparameterTime < Module # :nodoc: + module Helpers # :nodoc: all + class AcceptsMultiparameterTime < Module def initialize(defaults: {}) define_method(:cast) do |value| if value.is_a?(Hash) diff --git a/activemodel/lib/active_model/type/helpers/mutable.rb b/activemodel/lib/active_model/type/helpers/mutable.rb index 4dddbe4e5e..f3a17a1698 100644 --- a/activemodel/lib/active_model/type/helpers/mutable.rb +++ b/activemodel/lib/active_model/type/helpers/mutable.rb @@ -1,7 +1,7 @@ module ActiveModel module Type - module Helpers - module Mutable # :nodoc: + module Helpers # :nodoc: all + module Mutable def cast(value) deserialize(serialize(value)) end diff --git a/activemodel/lib/active_model/type/helpers/numeric.rb b/activemodel/lib/active_model/type/helpers/numeric.rb index c883010506..275822b738 100644 --- a/activemodel/lib/active_model/type/helpers/numeric.rb +++ b/activemodel/lib/active_model/type/helpers/numeric.rb @@ -1,14 +1,15 @@ module ActiveModel module Type - module Helpers - module Numeric # :nodoc: + module Helpers # :nodoc: all + module Numeric def cast(value) - value = case value - when true then 1 - when false then 0 - when ::String then value.presence - else value - end + value = \ + case value + when true then 1 + when false then 0 + when ::String then value.presence + else value + end super(value) end @@ -18,16 +19,16 @@ module ActiveModel private - def number_to_non_number?(old_value, new_value_before_type_cast) - old_value != nil && non_numeric_string?(new_value_before_type_cast) - end + def number_to_non_number?(old_value, new_value_before_type_cast) + old_value != nil && non_numeric_string?(new_value_before_type_cast) + end - def non_numeric_string?(value) - # 'wibble'.to_i will give zero, we want to make sure - # that we aren't marking int zero to string zero as - # changed. - value.to_s !~ /\A-?\d+\.?\d*\z/ - end + def non_numeric_string?(value) + # 'wibble'.to_i will give zero, we want to make sure + # that we aren't marking int zero to string zero as + # changed. + value.to_s !~ /\A-?\d+\.?\d*\z/ + end end end end diff --git a/activemodel/lib/active_model/type/helpers/time_value.rb b/activemodel/lib/active_model/type/helpers/time_value.rb index 63993c0d93..e57a52104b 100644 --- a/activemodel/lib/active_model/type/helpers/time_value.rb +++ b/activemodel/lib/active_model/type/helpers/time_value.rb @@ -2,8 +2,8 @@ require "active_support/core_ext/time/zones" module ActiveModel module Type - module Helpers - module TimeValue # :nodoc: + module Helpers # :nodoc: all + module TimeValue def serialize(value) value = apply_seconds_precision(value) @@ -19,7 +19,7 @@ module ActiveModel end def is_utc? - ::Time.zone_default.nil? || ::Time.zone_default =~ 'UTC' + ::Time.zone_default.nil? || ::Time.zone_default =~ "UTC" end def default_timezone @@ -33,8 +33,8 @@ module ActiveModel def apply_seconds_precision(value) return value unless precision && value.respond_to?(:usec) number_of_insignificant_digits = 6 - precision - round_power = 10 ** number_of_insignificant_digits - value.change(usec: value.usec / round_power * round_power) + round_power = 10**number_of_insignificant_digits + value.change(usec: value.usec - value.usec % round_power) end def type_cast_for_schema(value) @@ -47,30 +47,30 @@ module ActiveModel private - def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil) - # Treat 0000-00-00 00:00:00 as nil. - return if year.nil? || (year == 0 && mon == 0 && mday == 0) + def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil) + # Treat 0000-00-00 00:00:00 as nil. + return if year.nil? || (year == 0 && mon == 0 && mday == 0) - if offset - time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil - return unless time + if offset + time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil + return unless time - time -= offset - is_utc? ? time : time.getlocal - else - ::Time.public_send(default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil + time -= offset + is_utc? ? time : time.getlocal + else + ::Time.public_send(default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil + end end - end - ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/ + ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/ - # Doesn't handle time zones. - def fast_string_to_time(string) - if string =~ ISO_DATETIME - microsec = ($7.to_r * 1_000_000).to_i - new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec + # Doesn't handle time zones. + def fast_string_to_time(string) + if string =~ ISO_DATETIME + microsec = ($7.to_r * 1_000_000).to_i + new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec + end end - end end end end diff --git a/activemodel/lib/active_model/type/immutable_string.rb b/activemodel/lib/active_model/type/immutable_string.rb index 20b8ca0cc4..58268540e5 100644 --- a/activemodel/lib/active_model/type/immutable_string.rb +++ b/activemodel/lib/active_model/type/immutable_string.rb @@ -16,14 +16,15 @@ module ActiveModel private - def cast_value(value) - result = case value - when true then "t" - when false then "f" - else value.to_s - end - result.freeze - end + def cast_value(value) + result = \ + case value + when true then "t" + when false then "f" + else value.to_s + end + result.freeze + end end end end diff --git a/activemodel/lib/active_model/type/integer.rb b/activemodel/lib/active_model/type/integer.rb index eea2280b22..230e45ba60 100644 --- a/activemodel/lib/active_model/type/integer.rb +++ b/activemodel/lib/active_model/type/integer.rb @@ -29,38 +29,40 @@ module ActiveModel result end + # TODO Change this to private once we've dropped Ruby 2.2 support. + # Workaround for Ruby 2.2 "private attribute?" warning. protected - attr_reader :range + attr_reader :range private - def cast_value(value) - case value - when true then 1 - when false then 0 - else - value.to_i rescue nil + def cast_value(value) + case value + when true then 1 + when false then 0 + else + value.to_i rescue nil + end end - end - def ensure_in_range(value) - unless range.cover?(value) - raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit}" + def ensure_in_range(value) + unless range.cover?(value) + raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit}" + end end - end - def max_value - 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign - end + def max_value + 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign + end - def min_value - -max_value - end + def min_value + -max_value + end - def _limit - self.limit || DEFAULT_LIMIT - end + def _limit + limit || DEFAULT_LIMIT + end end end end diff --git a/activemodel/lib/active_model/type/registry.rb b/activemodel/lib/active_model/type/registry.rb index adc88eb624..2d5dd366eb 100644 --- a/activemodel/lib/active_model/type/registry.rb +++ b/activemodel/lib/active_model/type/registry.rb @@ -21,19 +21,21 @@ module ActiveModel end end + # TODO Change this to private once we've dropped Ruby 2.2 support. + # Workaround for Ruby 2.2 "private attribute?" warning. protected - attr_reader :registrations + attr_reader :registrations private - def registration_klass - Registration - end + def registration_klass + Registration + end - def find_registration(symbol, *args) - registrations.find { |r| r.matches?(symbol, *args) } - end + def find_registration(symbol, *args) + registrations.find { |r| r.matches?(symbol, *args) } + end end class Registration @@ -55,9 +57,11 @@ module ActiveModel type_name == name end + # TODO Change this to private once we've dropped Ruby 2.2 support. + # Workaround for Ruby 2.2 "private attribute?" warning. protected - attr_reader :name, :block + attr_reader :name, :block end end # :startdoc: diff --git a/activemodel/lib/active_model/type/string.rb b/activemodel/lib/active_model/type/string.rb index 8a91410998..c7e0208a5a 100644 --- a/activemodel/lib/active_model/type/string.rb +++ b/activemodel/lib/active_model/type/string.rb @@ -11,9 +11,9 @@ module ActiveModel private - def cast_value(value) - ::String.new(super) - end + def cast_value(value) + ::String.new(super) + end end end end diff --git a/activemodel/lib/active_model/type/text.rb b/activemodel/lib/active_model/type/text.rb deleted file mode 100644 index 1ad04daba4..0000000000 --- a/activemodel/lib/active_model/type/text.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'active_model/type/string' - -module ActiveModel - module Type - class Text < String # :nodoc: - def type - :text - end - end - end -end diff --git a/activemodel/lib/active_model/type/time.rb b/activemodel/lib/active_model/type/time.rb index 34e09f0aba..54d6214e81 100644 --- a/activemodel/lib/active_model/type/time.rb +++ b/activemodel/lib/active_model/type/time.rb @@ -25,22 +25,22 @@ module ActiveModel private - def cast_value(value) - return value unless value.is_a?(::String) - return if value.empty? - - if value =~ /^2000-01-01/ - dummy_time_value = value - else - dummy_time_value = "2000-01-01 #{value}" + def cast_value(value) + return value unless value.is_a?(::String) + return if value.empty? + + if value.start_with?("2000-01-01") + dummy_time_value = value + else + dummy_time_value = "2000-01-01 #{value}" + end + + fast_string_to_time(dummy_time_value) || begin + time_hash = ::Date._parse(dummy_time_value) + return if time_hash[:hour].nil? + new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) + end end - - fast_string_to_time(dummy_time_value) || begin - time_hash = ::Date._parse(dummy_time_value) - return if time_hash[:hour].nil? - new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)) - end - end end end end diff --git a/activemodel/lib/active_model/type/unsigned_integer.rb b/activemodel/lib/active_model/type/unsigned_integer.rb deleted file mode 100644 index 3f49f9f5f7..0000000000 --- a/activemodel/lib/active_model/type/unsigned_integer.rb +++ /dev/null @@ -1,15 +0,0 @@ -module ActiveModel - module Type - class UnsignedInteger < Integer # :nodoc: - private - - def max_value - super * 2 - end - - def min_value - 0 - end - end - end -end diff --git a/activemodel/lib/active_model/type/value.rb b/activemodel/lib/active_model/type/value.rb index 0d2d6873a8..7e9ae92245 100644 --- a/activemodel/lib/active_model/type/value.rb +++ b/activemodel/lib/active_model/type/value.rb @@ -105,12 +105,12 @@ module ActiveModel private - # Convenience method for types which do not need separate type casting - # behavior for user and database inputs. Called by Value#cast for - # values except +nil+. - def cast_value(value) # :doc: - value - end + # Convenience method for types which do not need separate type casting + # behavior for user and database inputs. Called by Value#cast for + # values except +nil+. + def cast_value(value) # :doc: + value + end end end end diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index a10d2285a2..d460068830 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -1,9 +1,8 @@ -require 'active_support/core_ext/array/extract_options' -require 'active_support/core_ext/hash/keys' -require 'active_support/core_ext/hash/except' +require "active_support/core_ext/array/extract_options" +require "active_support/core_ext/hash/keys" +require "active_support/core_ext/hash/except" module ActiveModel - # == Active \Model \Validations # # Provides a full validation framework to your objects. @@ -51,7 +50,7 @@ module ActiveModel define_callbacks :validate, scope: :name class_attribute :_validators, instance_writer: false - self._validators = Hash.new { |h,k| h[k] = [] } + self._validators = Hash.new { |h, k| h[k] = [] } end module ClassMethods @@ -69,7 +68,7 @@ module ActiveModel # # Options: # * <tt>:on</tt> - Specifies the contexts where this validation is active. - # Runs in all validation contexts by default (nil). You can pass a symbol + # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. <tt>on: :create</tt> or # <tt>on: :custom_validation_context</tt> or # <tt>on: [:create, :custom_validation_context]</tt>) @@ -135,7 +134,7 @@ module ActiveModel # # Options: # * <tt>:on</tt> - Specifies the contexts where this validation is active. - # Runs in all validation contexts by default (nil). You can pass a symbol + # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. <tt>on: :create</tt> or # <tt>on: :custom_validation_context</tt> or # <tt>on: [:create, :custom_validation_context]</tt>) @@ -400,14 +399,14 @@ module ActiveModel # end alias :read_attribute_for_validation :send - protected + private - def run_validations! #:nodoc: + def run_validations! _run_validate_callbacks errors.empty? end - def raise_validation_error + def raise_validation_error # :doc: raise(ValidationError.new(self)) end end diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index a04e5f347e..e11005b9ba 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -1,5 +1,4 @@ module ActiveModel - module Validations class AcceptanceValidator < EachValidator # :nodoc: def initialize(options) @@ -15,58 +14,60 @@ module ActiveModel private - def setup!(klass) - klass.include(LazilyDefineAttributes.new(AttributeDefinition.new(attributes))) - end + def setup!(klass) + klass.include(LazilyDefineAttributes.new(AttributeDefinition.new(attributes))) + end - def acceptable_option?(value) - Array(options[:accept]).include?(value) - end + def acceptable_option?(value) + Array(options[:accept]).include?(value) + end - class LazilyDefineAttributes < Module - def initialize(attribute_definition) - define_method(:respond_to_missing?) do |method_name, include_private=false| - super(method_name, include_private) || attribute_definition.matches?(method_name) - end + class LazilyDefineAttributes < Module + def initialize(attribute_definition) + define_method(:respond_to_missing?) do |method_name, include_private = false| + super(method_name, include_private) || attribute_definition.matches?(method_name) + end - define_method(:method_missing) do |method_name, *args, &block| - if attribute_definition.matches?(method_name) - attribute_definition.define_on(self.class) - send(method_name, *args, &block) - else - super(method_name, *args, &block) + define_method(:method_missing) do |method_name, *args, &block| + if attribute_definition.matches?(method_name) + attribute_definition.define_on(self.class) + send(method_name, *args, &block) + else + super(method_name, *args, &block) + end end end end - end - class AttributeDefinition - def initialize(attributes) - @attributes = attributes.map(&:to_s) - end + class AttributeDefinition + def initialize(attributes) + @attributes = attributes.map(&:to_s) + end - def matches?(method_name) - attr_name = convert_to_reader_name(method_name) - attributes.include?(attr_name) - end + def matches?(method_name) + attr_name = convert_to_reader_name(method_name) + attributes.include?(attr_name) + end - def define_on(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) - klass.send(:attr_writer, *attr_writers) - end + def define_on(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) + klass.send(:attr_writer, *attr_writers) + end - protected + # TODO Change this to private once we've dropped Ruby 2.2 support. + # Workaround for Ruby 2.2 "private attribute?" warning. + protected - attr_reader :attributes + attr_reader :attributes - private + private - def convert_to_reader_name(method_name) - method_name.to_s.chomp('=') + def convert_to_reader_name(method_name) + method_name.to_s.chomp("=") + end end - end end module HelperMethods diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index a201f72ed0..70bc1a0624 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -104,10 +104,10 @@ module ActiveModel end end - protected + private # Overwrite run validations to include callbacks. - def run_validations! #:nodoc: + def run_validations! _run_validation_callbacks { super } end end diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb index d49af603bb..18f1056e2b 100644 --- a/activemodel/lib/active_model/validations/clusivity.rb +++ b/activemodel/lib/active_model/validations/clusivity.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/range' +require "active_support/core_ext/range" module ActiveModel module Validations @@ -16,12 +16,12 @@ module ActiveModel def include?(record, value) members = if delimiter.respond_to?(:call) - delimiter.call(record) - elsif delimiter.respond_to?(:to_sym) - record.send(delimiter) - else - delimiter - end + delimiter.call(record) + elsif delimiter.respond_to?(:to_sym) + record.send(delimiter) + else + delimiter + end members.send(inclusion_method(members), value) end diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 8f8ade90bb..33ca6f6946 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -1,5 +1,4 @@ module ActiveModel - module Validations class ConfirmationValidator < EachValidator # :nodoc: def initialize(options) @@ -17,23 +16,23 @@ module ActiveModel end private - def setup!(klass) - klass.send(:attr_reader, *attributes.map do |attribute| - :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation") - end.compact) + def setup!(klass) + klass.send(:attr_reader, *attributes.map do |attribute| + :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation") + end.compact) - klass.send(:attr_writer, *attributes.map do |attribute| - :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=") - end.compact) - end + klass.send(:attr_writer, *attributes.map do |attribute| + :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=") + end.compact) + end - def confirmation_value_equal?(record, attribute, value, confirmed) - if !options[:case_sensitive] && value.is_a?(String) - value.casecmp(confirmed) == 0 - else - value == confirmed + def confirmation_value_equal?(record, attribute, value, confirmed) + if !options[:case_sensitive] && value.is_a?(String) + value.casecmp(confirmed) == 0 + else + value == confirmed + end end - end end module HelperMethods diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index 6f4276cc2a..82a1893823 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -1,7 +1,6 @@ require "active_model/validations/clusivity" module ActiveModel - module Validations class ExclusionValidator < EachValidator # :nodoc: include Clusivity diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 46a2e54fba..fa183885ab 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -1,5 +1,5 @@ -module ActiveModel +module ActiveModel module Validations class FormatValidator < EachValidator # :nodoc: def validate_each(record, attribute, value) @@ -8,7 +8,7 @@ module ActiveModel record_error(record, attribute, :with, value) if value.to_s !~ regexp elsif options[:without] regexp = option_call(record, :without) - record_error(record, attribute, :without, value) if value.to_s =~ regexp + record_error(record, attribute, :without, value) if regexp.match?(value.to_s) end end @@ -23,33 +23,33 @@ module ActiveModel private - def option_call(record, name) - option = options[name] - option.respond_to?(:call) ? option.call(record) : option - end + def option_call(record, name) + option = options[name] + option.respond_to?(:call) ? option.call(record) : option + end - def record_error(record, attribute, name, value) - record.errors.add(attribute, :invalid, options.except(name).merge!(value: value)) - end + def record_error(record, attribute, name, value) + record.errors.add(attribute, :invalid, options.except(name).merge!(value: value)) + end - def check_options_validity(name) - if option = options[name] - if option.is_a?(Regexp) - if options[:multiline] != true && regexp_using_multiline_anchors?(option) - raise ArgumentError, "The provided regular expression is using multiline anchors (^ or $), " \ - "which may present a security risk. Did you mean to use \\A and \\z, or forgot to add the " \ - ":multiline => true option?" + def check_options_validity(name) + if option = options[name] + if option.is_a?(Regexp) + if options[:multiline] != true && regexp_using_multiline_anchors?(option) + raise ArgumentError, "The provided regular expression is using multiline anchors (^ or $), " \ + "which may present a security risk. Did you mean to use \\A and \\z, or forgot to add the " \ + ":multiline => true option?" + end + elsif !option.respond_to?(:call) + raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}" end - elsif !option.respond_to?(:call) - raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}" end end - end - def regexp_using_multiline_anchors?(regexp) - source = regexp.source - source.start_with?("^") || (source.end_with?("$") && !source.end_with?("\\$")) - end + def regexp_using_multiline_anchors?(regexp) + source = regexp.source + source.start_with?("^") || (source.end_with?("$") && !source.end_with?("\\$")) + end end module HelperMethods diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 03e0ef56d8..0ea6012a5d 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -1,7 +1,6 @@ require "active_model/validations/clusivity" module ActiveModel - module Validations class InclusionValidator < EachValidator # :nodoc: include Clusivity diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 79297ac119..de1524829e 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -6,7 +6,7 @@ module ActiveModel MESSAGES = { is: :wrong_length, minimum: :too_short, maximum: :too_long }.freeze CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze - RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long] + RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :too_short, :too_long] def initialize(options) if range = (options.delete(:in) || options.delete(:within)) @@ -18,27 +18,6 @@ module ActiveModel options[:minimum] = 1 end - if options[:tokenizer] - ActiveSupport::Deprecation.warn(<<-EOS.strip_heredoc) - The `:tokenizer` option is deprecated, and will be removed in Rails 5.1. - You can achieve the same functionality by defining an instance method - with the value that you want to validate the length of. For example, - - validates_length_of :essay, minimum: 100, - tokenizer: ->(str) { str.scan(/\w+/) } - - should be written as - - validates_length_of :words_in_essay, minimum: 100 - - private - - def words_in_essay - essay.scan(/\w+/) - end - EOS - end - super end @@ -46,7 +25,7 @@ module ActiveModel keys = CHECKS.keys & options.keys if keys.empty? - raise ArgumentError, 'Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.' + raise ArgumentError, "Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option." end keys.each do |key| @@ -59,7 +38,6 @@ module ActiveModel end def validate_each(record, attribute, value) - value = tokenize(record, value) value_length = value.respond_to?(:length) ? value.length : value.to_s.length errors_options = options.except(*RESERVED_OPTIONS) @@ -80,24 +58,12 @@ module ActiveModel end private - def tokenize(record, value) - tokenizer = options[:tokenizer] - if tokenizer && value.kind_of?(String) - if tokenizer.kind_of?(Proc) - tokenizer.call(value) - elsif record.respond_to?(tokenizer) - record.send(tokenizer, value) - end - end || value - end - - def skip_nil_check?(key) - key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil? - end + def skip_nil_check?(key) + key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil? + end end module HelperMethods - # Validates that the specified attributes match the length restrictions # supplied. Only one constraint option can be used at a time apart from # +:minimum+ and +:maximum+ that can be combined together: diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 9a0a0655de..2297faaee5 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -1,5 +1,4 @@ module ActiveModel - module Validations class NumericalityValidator < EachValidator # :nodoc: CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=, @@ -27,8 +26,6 @@ module ActiveModel raw_value = value end - return if options[:allow_nil] && raw_value.nil? - unless is_number?(raw_value) record.errors.add(attr_name, :not_a_number, filtered_options(raw_value)) return @@ -64,29 +61,29 @@ module ActiveModel end end - protected + private - def is_number?(raw_value) + def is_number?(raw_value) # :doc: !parse_raw_value_as_a_number(raw_value).nil? rescue ArgumentError, TypeError false end - def parse_raw_value_as_a_number(raw_value) + def parse_raw_value_as_a_number(raw_value) # :doc: Kernel.Float(raw_value) if raw_value !~ /\A0[xX]/ end - def is_integer?(raw_value) + def is_integer?(raw_value) # :doc: /\A[+-]?\d+\z/ === raw_value.to_s end - def filtered_options(value) + def filtered_options(value) # :doc: filtered = options.except(*RESERVED_OPTIONS) filtered[:value] = value filtered end - def allow_only_integer?(record) + def allow_only_integer?(record) # :doc: case options[:only_integer] when Symbol record.send(options[:only_integer]) @@ -97,8 +94,6 @@ module ActiveModel end end - private - def record_attribute_changed_in_place?(record, attr_name) record.respond_to?(:attribute_changed_in_place?) && record.attribute_changed_in_place?(attr_name.to_s) diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 5d593274eb..0c11cf4265 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -1,6 +1,5 @@ module ActiveModel - module Validations class PresenceValidator < EachValidator # :nodoc: def validate_each(record, attr_name, value) diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 1da4df21e7..0ce5935f3a 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/hash/slice' +require "active_support/core_ext/hash/slice" module ActiveModel module Validations @@ -72,7 +72,7 @@ module ActiveModel # There is also a list of options that could be used along with validators: # # * <tt>:on</tt> - Specifies the contexts where this validation is active. - # Runs in all validation contexts by default (nil). You can pass a symbol + # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. <tt>on: :create</tt> or # <tt>on: :custom_validation_context</tt> or # <tt>on: [:create, :custom_validation_context]</tt>) @@ -115,7 +115,7 @@ module ActiveModel key = "#{key.to_s.camelize}Validator" begin - validator = key.include?('::'.freeze) ? key.constantize : const_get(key) + validator = key.include?("::".freeze) ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end @@ -148,15 +148,15 @@ module ActiveModel validates(*(attributes << options)) end - protected + private # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. - def _validates_default_keys # :nodoc: + def _validates_default_keys [:if, :unless, :on, :allow_blank, :allow_nil , :strict] end - def _parse_validates_options(options) # :nodoc: + def _parse_validates_options(options) case options when TrueClass {} diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 6de01b3392..e3f7a9bcb2 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -1,3 +1,5 @@ +require "active_support/core_ext/array/extract_options" + module ActiveModel module Validations class WithValidator < EachValidator # :nodoc: @@ -43,7 +45,7 @@ module ActiveModel # # Configuration options: # * <tt>:on</tt> - Specifies the contexts where this validation is active. - # Runs in all validation contexts by default (nil). You can pass a symbol + # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. <tt>on: :create</tt> or # <tt>on: :custom_validation_context</tt> or # <tt>on: [:create, :custom_validation_context]</tt>) diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 699f74ed17..8212744170 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -1,7 +1,6 @@ require "active_support/core_ext/module/anonymous" module ActiveModel - # == Active \Model \Validator # # A simple base class that can be used along with @@ -100,12 +99,12 @@ module ActiveModel # PresenceValidator.kind # => :presence # UniquenessValidator.kind # => :uniqueness def self.kind - @kind ||= name.split('::').last.underscore.chomp('_validator').to_sym unless anonymous? + @kind ||= name.split("::").last.underscore.chomp("_validator").to_sym unless anonymous? end # Accepts options that will be made available through the +options+ reader. def initialize(options = {}) - @options = options.except(:class).freeze + @options = options.except(:class).freeze end # Returns the kind for this validator. @@ -175,8 +174,8 @@ module ActiveModel private - def validate_each(record, attribute, value) - @block.call(record, attribute, value) - end + def validate_each(record, attribute, value) + @block.call(record, attribute, value) + end end end diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb index 6da3b4117b..6e7fd227fd 100644 --- a/activemodel/lib/active_model/version.rb +++ b/activemodel/lib/active_model/version.rb @@ -1,4 +1,4 @@ -require_relative 'gem_version' +require_relative "gem_version" module ActiveModel # Returns the version of the currently loaded \Active \Model as a <tt>Gem::Version</tt> diff --git a/activemodel/test/cases/attribute_assignment_test.rb b/activemodel/test/cases/attribute_assignment_test.rb index 287bea719c..fa41d1b95f 100644 --- a/activemodel/test/cases/attribute_assignment_test.rb +++ b/activemodel/test/cases/attribute_assignment_test.rb @@ -16,9 +16,11 @@ class AttributeAssignmentTest < ActiveModel::TestCase raise ErrorFromAttributeWriter end + # TODO Change this to private once we've dropped Ruby 2.2 support. + # Workaround for Ruby 2.2 "private attribute?" warning. protected - attr_writer :metadata + attr_writer :metadata end class ErrorFromAttributeWriter < StandardError diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index e81b7ac424..4767accb7c 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -1,16 +1,16 @@ -require 'cases/helper' +require "cases/helper" class ModelWithAttributes include ActiveModel::AttributeMethods class << self define_method(:bar) do - 'original bar' + "original bar" end end def attributes - { foo: 'value of foo', baz: 'value of baz' } + { foo: "value of foo", baz: "value of baz" } end private @@ -24,7 +24,7 @@ class ModelWithAttributes2 attr_accessor :attributes - attribute_method_suffix '_test' + attribute_method_suffix "_test" private def attribute(name) @@ -48,7 +48,7 @@ class ModelWithAttributesWithSpaces include ActiveModel::AttributeMethods def attributes - { :'foo bar' => 'value of foo bar'} + { 'foo bar': "value of foo bar" } end private @@ -62,12 +62,12 @@ class ModelWithWeirdNamesAttributes class << self define_method(:'c?d') do - 'original c?d' + "original c?d" end end def attributes - { :'a?b' => 'value of a?b' } + { 'a?b': "value of a?b" } end private @@ -80,7 +80,7 @@ class ModelWithRubyKeywordNamedAttributes include ActiveModel::AttributeMethods def attributes - { begin: 'value of begin', end: 'value of end' } + { begin: "value of begin", end: "value of end" } end private @@ -94,16 +94,16 @@ class ModelWithoutAttributesMethod end class AttributeMethodsTest < ActiveModel::TestCase - test 'method missing works correctly even if attributes method is not defined' do + test "method missing works correctly even if attributes method is not defined" do assert_raises(NoMethodError) { ModelWithoutAttributesMethod.new.foo } end - test 'unrelated classes should not share attribute method matchers' do + test "unrelated classes should not share attribute method matchers" do assert_not_equal ModelWithAttributes.send(:attribute_method_matchers), ModelWithAttributes2.send(:attribute_method_matchers) end - test '#define_attribute_method generates attribute method' do + test "#define_attribute_method generates attribute method" do begin ModelWithAttributes.define_attribute_method(:foo) @@ -114,19 +114,19 @@ class AttributeMethodsTest < ActiveModel::TestCase end end - test '#define_attribute_method does not generate attribute method if already defined in attribute module' do + test "#define_attribute_method does not generate attribute method if already defined in attribute module" do klass = Class.new(ModelWithAttributes) klass.generated_attribute_methods.module_eval do def foo - '<3' + "<3" end end klass.define_attribute_method(:foo) - assert_equal '<3', klass.new.foo + assert_equal "<3", klass.new.foo end - test '#define_attribute_method generates a method that is already defined on the host' do + test "#define_attribute_method generates a method that is already defined on the host" do klass = Class.new(ModelWithAttributes) do def foo super @@ -134,21 +134,21 @@ class AttributeMethodsTest < ActiveModel::TestCase end klass.define_attribute_method(:foo) - assert_equal 'value of foo', klass.new.foo + assert_equal "value of foo", klass.new.foo end - test '#define_attribute_method generates attribute method with invalid identifier characters' do + test "#define_attribute_method generates attribute method with invalid identifier characters" do begin ModelWithWeirdNamesAttributes.define_attribute_method(:'a?b') assert_respond_to ModelWithWeirdNamesAttributes.new, :'a?b' - assert_equal "value of a?b", ModelWithWeirdNamesAttributes.new.send('a?b') + assert_equal "value of a?b", ModelWithWeirdNamesAttributes.new.send("a?b") ensure ModelWithWeirdNamesAttributes.undefine_attribute_methods end end - test '#define_attribute_methods works passing multiple arguments' do + test "#define_attribute_methods works passing multiple arguments" do begin ModelWithAttributes.define_attribute_methods(:foo, :baz) @@ -159,7 +159,7 @@ class AttributeMethodsTest < ActiveModel::TestCase end end - test '#define_attribute_methods generates attribute methods' do + test "#define_attribute_methods generates attribute methods" do begin ModelWithAttributes.define_attribute_methods(:foo) @@ -170,7 +170,7 @@ class AttributeMethodsTest < ActiveModel::TestCase end end - test '#alias_attribute generates attribute_aliases lookup hash' do + test "#alias_attribute generates attribute_aliases lookup hash" do klass = Class.new(ModelWithAttributes) do define_attribute_methods :foo alias_attribute :bar, :foo @@ -179,7 +179,7 @@ class AttributeMethodsTest < ActiveModel::TestCase assert_equal({ "bar" => "foo" }, klass.attribute_aliases) end - test '#define_attribute_methods generates attribute methods with spaces in their names' do + test "#define_attribute_methods generates attribute methods with spaces in their names" do begin ModelWithAttributesWithSpaces.define_attribute_methods(:'foo bar') @@ -190,7 +190,7 @@ class AttributeMethodsTest < ActiveModel::TestCase end end - test '#alias_attribute works with attributes with spaces in their names' do + test "#alias_attribute works with attributes with spaces in their names" do begin ModelWithAttributesWithSpaces.define_attribute_methods(:'foo bar') ModelWithAttributesWithSpaces.alias_attribute(:'foo_bar', :'foo bar') @@ -201,7 +201,7 @@ class AttributeMethodsTest < ActiveModel::TestCase end end - test '#alias_attribute works with attributes named as a ruby keyword' do + test "#alias_attribute works with attributes named as a ruby keyword" do begin ModelWithRubyKeywordNamedAttributes.define_attribute_methods([:begin, :end]) ModelWithRubyKeywordNamedAttributes.alias_attribute(:from, :begin) @@ -214,7 +214,7 @@ class AttributeMethodsTest < ActiveModel::TestCase end end - test '#undefine_attribute_methods removes attribute methods' do + test "#undefine_attribute_methods removes attribute methods" do ModelWithAttributes.define_attribute_methods(:foo) ModelWithAttributes.undefine_attribute_methods @@ -222,21 +222,21 @@ class AttributeMethodsTest < ActiveModel::TestCase assert_raises(NoMethodError) { ModelWithAttributes.new.foo } end - test 'accessing a suffixed attribute' do + test "accessing a suffixed attribute" do m = ModelWithAttributes2.new - m.attributes = { 'foo' => 'bar' } + m.attributes = { "foo" => "bar" } - assert_equal 'bar', m.foo - assert_equal 'bar', m.foo_test + assert_equal "bar", m.foo + assert_equal "bar", m.foo_test end - test 'should not interfere with method_missing if the attr has a private/protected method' do + test "should not interfere with method_missing if the attr has a private/protected method" do m = ModelWithAttributes2.new - m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' } + m.attributes = { "private_method" => "<3", "protected_method" => "O_o" } # dispatches to the *method*, not the attribute - assert_equal '<3 <3', m.send(:private_method) - assert_equal 'O_o O_o', m.send(:protected_method) + assert_equal "<3 <3", m.send(:private_method) + assert_equal "O_o O_o", m.send(:protected_method) # sees that a method is already defined, so doesn't intervene assert_raises(NoMethodError) { m.private_method } @@ -245,13 +245,13 @@ class AttributeMethodsTest < ActiveModel::TestCase class ClassWithProtected protected - def protected_method - end + def protected_method + end end - test 'should not interfere with respond_to? if the attribute has a private/protected method' do + test "should not interfere with respond_to? if the attribute has a private/protected method" do m = ModelWithAttributes2.new - m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' } + m.attributes = { "private_method" => "<3", "protected_method" => "O_o" } assert !m.respond_to?(:private_method) assert m.respond_to?(:private_method, true) @@ -264,9 +264,9 @@ class AttributeMethodsTest < ActiveModel::TestCase assert m.respond_to?(:protected_method, true) end - test 'should use attribute_missing to dispatch a missing attribute' do + test "should use attribute_missing to dispatch a missing attribute" do m = ModelWithAttributes2.new - m.attributes = { 'foo' => 'bar' } + m.attributes = { "foo" => "bar" } def m.attribute_missing(match, *args, &block) match @@ -274,8 +274,8 @@ class AttributeMethodsTest < ActiveModel::TestCase match = m.foo_test - assert_equal 'foo', match.attr_name - assert_equal 'attribute_test', match.target - assert_equal 'foo_test', match.method_name + assert_equal "foo", match.attr_name + assert_equal "attribute_test", match.target + assert_equal "foo_test", match.method_name end end diff --git a/activemodel/test/cases/callbacks_test.rb b/activemodel/test/cases/callbacks_test.rb index e4ecc0adb4..63b6c56f8c 100644 --- a/activemodel/test/cases/callbacks_test.rb +++ b/activemodel/test/cases/callbacks_test.rb @@ -1,7 +1,6 @@ require "cases/helper" class CallbacksTest < ActiveModel::TestCase - class CallbackValidator def around_create(model) model.callbacks << :before_around_create @@ -110,8 +109,8 @@ class CallbacksTest < ActiveModel::TestCase end extend ActiveModel::Callbacks define_model_callbacks :create - def callback1; self.history << 'callback1'; end - def callback2; self.history << 'callback2'; end + def callback1; history << "callback1"; end + def callback2; history << "callback2"; end def create run_callbacks(:create) {} self @@ -131,5 +130,4 @@ class CallbacksTest < ActiveModel::TestCase test "after_create callbacks with both callbacks declared in different lines" do assert_equal ["callback1", "callback2"], Violin2.new.create.history end - end diff --git a/activemodel/test/cases/conversion_test.rb b/activemodel/test/cases/conversion_test.rb index 800cad6d9a..4a93347abc 100644 --- a/activemodel/test/cases/conversion_test.rb +++ b/activemodel/test/cases/conversion_test.rb @@ -1,6 +1,6 @@ -require 'cases/helper' -require 'models/contact' -require 'models/helicopter' +require "cases/helper" +require "models/contact" +require "models/helicopter" class ConversionTest < ActiveModel::TestCase test "to_model default implementation returns self" do diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb index d17a12ad12..fdd18d7601 100644 --- a/activemodel/test/cases/dirty_test.rb +++ b/activemodel/test/cases/dirty_test.rb @@ -62,13 +62,13 @@ class DirtyTest < ActiveModel::TestCase test "list of changed attribute keys" do assert_equal [], @model.changed @model.name = "Paul" - assert_equal ['name'], @model.changed + assert_equal ["name"], @model.changed end test "changes to attribute values" do - assert !@model.changes['name'] + assert !@model.changes["name"] @model.name = "John" - assert_equal [nil, "John"], @model.changes['name'] + assert_equal [nil, "John"], @model.changes["name"] end test "checking if an attribute has changed to a particular value" do @@ -84,14 +84,14 @@ class DirtyTest < ActiveModel::TestCase test "changes accessible through both strings and symbols" do @model.name = "David" assert_not_nil @model.changes[:name] - assert_not_nil @model.changes['name'] + assert_not_nil @model.changes["name"] end test "be consistent with symbols arguments after the changes are applied" do @model.name = "David" assert @model.attribute_changed?(:name) @model.save - @model.name = 'Rafael' + @model.name = "Rafael" assert @model.attribute_changed?(:name) end @@ -134,7 +134,7 @@ class DirtyTest < ActiveModel::TestCase test "saving should preserve previous changes" do @model.name = "Jericho Cane" @model.save - assert_equal [nil, "Jericho Cane"], @model.previous_changes['name'] + assert_equal [nil, "Jericho Cane"], @model.previous_changes["name"] end test "setting new attributes should not affect previous changes" do @@ -176,13 +176,13 @@ class DirtyTest < ActiveModel::TestCase end test "reload should reset all changes" do - @model.name = 'Dmitry' + @model.name = "Dmitry" @model.name_changed? @model.save - @model.name = 'Bob' + @model.name = "Bob" - assert_equal [nil, 'Dmitry'], @model.previous_changes['name'] - assert_equal 'Dmitry', @model.changed_attributes['name'] + assert_equal [nil, "Dmitry"], @model.previous_changes["name"] + assert_equal "Dmitry", @model.changed_attributes["name"] @model.reload @@ -191,30 +191,30 @@ class DirtyTest < ActiveModel::TestCase end test "restore_attributes should restore all previous data" do - @model.name = 'Dmitry' - @model.color = 'Red' + @model.name = "Dmitry" + @model.color = "Red" @model.save - @model.name = 'Bob' - @model.color = 'White' + @model.name = "Bob" + @model.color = "White" @model.restore_attributes assert_not @model.changed? - assert_equal 'Dmitry', @model.name - assert_equal 'Red', @model.color + assert_equal "Dmitry", @model.name + assert_equal "Red", @model.color end test "restore_attributes can restore only some attributes" do - @model.name = 'Dmitry' - @model.color = 'Red' + @model.name = "Dmitry" + @model.color = "Red" @model.save - @model.name = 'Bob' - @model.color = 'White' + @model.name = "Bob" + @model.color = "White" - @model.restore_attributes(['name']) + @model.restore_attributes(["name"]) assert @model.changed? - assert_equal 'Dmitry', @model.name - assert_equal 'White', @model.color + assert_equal "Dmitry", @model.name + assert_equal "White", @model.color end end diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb index c90ee7021c..e6ba06301d 100644 --- a/activemodel/test/cases/errors_test.rb +++ b/activemodel/test/cases/errors_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require "yaml" class ErrorsTest < ActiveModel::TestCase class Person @@ -29,45 +30,48 @@ class ErrorsTest < ActiveModel::TestCase def test_delete errors = ActiveModel::Errors.new(self) - errors[:foo] << 'omg' - errors.delete(:foo) + errors[:foo] << "omg" + errors.delete("foo") assert_empty errors[:foo] end def test_include? errors = ActiveModel::Errors.new(self) - errors[:foo] << 'omg' - assert errors.include?(:foo), 'errors should include :foo' + errors[:foo] << "omg" + assert_includes errors, :foo, "errors should include :foo" + assert_includes errors, "foo", "errors should include 'foo' as :foo" end def test_dup errors = ActiveModel::Errors.new(self) - errors[:foo] << 'bar' + errors[:foo] << "bar" errors_dup = errors.dup - errors_dup[:bar] << 'omg' + errors_dup[:bar] << "omg" assert_not_same errors_dup.messages, errors.messages end def test_has_key? errors = ActiveModel::Errors.new(self) - errors[:foo] << 'omg' - assert_equal true, errors.has_key?(:foo), 'errors should have key :foo' + errors[:foo] << "omg" + assert_equal true, errors.has_key?(:foo), "errors should have key :foo" + assert_equal true, errors.has_key?("foo"), "errors should have key 'foo' as :foo" end def test_has_no_key errors = ActiveModel::Errors.new(self) - assert_equal false, errors.has_key?(:name), 'errors should not have key :name' + assert_equal false, errors.has_key?(:name), "errors should not have key :name" end def test_key? errors = ActiveModel::Errors.new(self) - errors[:foo] << 'omg' - assert_equal true, errors.key?(:foo), 'errors should have key :foo' + errors[:foo] << "omg" + assert_equal true, errors.key?(:foo), "errors should have key :foo" + assert_equal true, errors.key?("foo"), "errors should have key 'foo' as :foo" end def test_no_key errors = ActiveModel::Errors.new(self) - assert_equal false, errors.key?(:name), 'errors should not have key :name' + assert_equal false, errors.key?(:name), "errors should not have key :name" end test "clear errors" do @@ -79,24 +83,6 @@ class ErrorsTest < ActiveModel::TestCase assert person.errors.empty? end - test "get returns the errors for the provided key" do - errors = ActiveModel::Errors.new(self) - errors[:foo] << "omg" - - assert_deprecated do - assert_equal ["omg"], errors.get(:foo) - end - end - - test "sets the error with the provided key" do - errors = ActiveModel::Errors.new(self) - assert_deprecated do - errors.set(:foo, "omg") - end - - assert_equal({ foo: "omg" }, errors.messages) - end - test "error access is indifferent" do errors = ActiveModel::Errors.new(self) errors[:foo] << "omg" @@ -125,7 +111,7 @@ class ErrorsTest < ActiveModel::TestCase person.errors[:foo] assert person.errors.empty? assert person.errors.blank? - assert !person.errors.include?(:foo) + assert_not_includes person.errors, :foo end test "include? does not add a key to messages hash" do @@ -142,14 +128,6 @@ class ErrorsTest < ActiveModel::TestCase assert_equal ["cannot be nil"], person.errors[:name] end - test "assign error" do - person = Person.new - assert_deprecated do - person.errors[:name] = 'should not be nil' - end - assert_equal ["should not be nil"], person.errors[:name] - end - test "add an error message on a specific attribute" do person = Person.new person.errors.add(:name, "cannot be blank") @@ -176,10 +154,11 @@ class ErrorsTest < ActiveModel::TestCase assert_equal ["cannot be blank"], person.errors[:name] end - test "added? detects if a specific error was added to the object" do + test "added? detects indifferent if a specific error was added to the object" do person = Person.new person.errors.add(:name, "cannot be blank") assert person.errors.added?(:name, "cannot be blank") + assert person.errors.added?("name", "cannot be blank") end test "added? handles symbol message" do @@ -219,6 +198,12 @@ class ErrorsTest < ActiveModel::TestCase assert !person.errors.added?(:name, "cannot be blank") end + test "added? returns false when checking for an error, but not providing message arguments" do + person = Person.new + person.errors.add(:name, "cannot be blank") + assert !person.errors.added?(:name) + end + test "size calculates the number of error messages" do person = Person.new person.errors.add(:name, "cannot be blank") @@ -244,6 +229,16 @@ class ErrorsTest < ActiveModel::TestCase assert_equal({ name: ["cannot be blank"] }, person.errors.to_hash) end + test "to_hash returns a hash without default proc" do + person = Person.new + assert_nil person.errors.to_hash.default_proc + end + + test "as_json returns a hash without default proc" do + person = Person.new + assert_nil person.errors.as_json.default_proc + end + test "full_messages creates a list of error messages with the attribute name included" do person = Person.new person.errors.add(:name, "cannot be blank") @@ -251,7 +246,7 @@ class ErrorsTest < ActiveModel::TestCase assert_equal ["name cannot be blank", "name cannot be nil"], person.errors.full_messages end - test "full_messages_for contains all the error messages for the given attribute" do + test "full_messages_for contains all the error messages for the given attribute indifferent" do person = Person.new person.errors.add(:name, "cannot be blank") person.errors.add(:name, "cannot be nil") @@ -263,6 +258,7 @@ class ErrorsTest < ActiveModel::TestCase person.errors.add(:name, "cannot be blank") person.errors.add(:email, "cannot be blank") assert_equal ["name cannot be blank"], person.errors.full_messages_for(:name) + assert_equal ["name cannot be blank"], person.errors.full_messages_for("name") end test "full_messages_for returns an empty list in case there are no errors for the given attribute" do @@ -304,72 +300,6 @@ class ErrorsTest < ActiveModel::TestCase } end - test "add_on_empty generates message" do - person = Person.new - assert_called_with(person.errors, :generate_message, [:name, :empty, {}]) do - assert_deprecated do - person.errors.add_on_empty :name - end - end - end - - test "add_on_empty generates message for multiple attributes" do - person = Person.new - expected_calls = [ [:name, :empty, {}], [:age, :empty, {}] ] - assert_called_with(person.errors, :generate_message, expected_calls) do - assert_deprecated do - person.errors.add_on_empty [:name, :age] - end - end - end - - test "add_on_empty generates message with custom default message" do - person = Person.new - assert_called_with(person.errors, :generate_message, [:name, :empty, { message: 'custom' }]) do - assert_deprecated do - person.errors.add_on_empty :name, message: 'custom' - end - end - end - - test "add_on_empty generates message with empty string value" do - person = Person.new - person.name = '' - assert_called_with(person.errors, :generate_message, [:name, :empty, {}]) do - assert_deprecated do - person.errors.add_on_empty :name - end - end - end - - test "add_on_blank generates message" do - person = Person.new - assert_called_with(person.errors, :generate_message, [:name, :blank, {}]) do - assert_deprecated do - person.errors.add_on_blank :name - end - end - end - - test "add_on_blank generates message for multiple attributes" do - person = Person.new - expected_calls = [ [:name, :blank, {}], [:age, :blank, {}] ] - assert_called_with(person.errors, :generate_message, expected_calls) do - assert_deprecated do - person.errors.add_on_blank [:name, :age] - end - end - end - - test "add_on_blank generates message with custom default message" do - person = Person.new - assert_called_with(person.errors, :generate_message, [:name, :blank, { message: 'custom' }]) do - assert_deprecated do - person.errors.add_on_blank :name, message: 'custom' - end - end - end - test "details returns added error detail" do person = Person.new person.errors.add(:name, :invalid) @@ -436,4 +366,24 @@ class ErrorsTest < ActiveModel::TestCase assert_equal errors.messages, serialized.messages assert_equal errors.details, serialized.details end + + test "errors are backward compatible with the Rails 4.2 format" do + yaml = <<-CODE.strip_heredoc + --- !ruby/object:ActiveModel::Errors + base: &1 !ruby/object:ErrorsTest::Person + errors: !ruby/object:ActiveModel::Errors + base: *1 + messages: {} + messages: {} + CODE + + errors = YAML.load(yaml) + errors.add(:name, :invalid) + assert_equal({ name: ["is invalid"] }, errors.messages) + assert_equal({ name: [{ error: :invalid }] }, errors.details) + + errors.clear + assert_equal({}, errors.messages) + assert_equal({}, errors.details) + end end diff --git a/activemodel/test/cases/forbidden_attributes_protection_test.rb b/activemodel/test/cases/forbidden_attributes_protection_test.rb index d8d757f52a..d8cc72e662 100644 --- a/activemodel/test/cases/forbidden_attributes_protection_test.rb +++ b/activemodel/test/cases/forbidden_attributes_protection_test.rb @@ -1,6 +1,6 @@ -require 'cases/helper' -require 'active_support/core_ext/hash/indifferent_access' -require 'models/account' +require "cases/helper" +require "active_support/core_ext/hash/indifferent_access" +require "models/account" class ProtectedParams attr_accessor :permitted @@ -25,18 +25,18 @@ end class ActiveModelMassUpdateProtectionTest < ActiveSupport::TestCase test "forbidden attributes cannot be used for mass updating" do - params = ProtectedParams.new({ "a" => "b" }) + params = ProtectedParams.new("a" => "b") assert_raises(ActiveModel::ForbiddenAttributesError) do Account.new.sanitize_for_mass_assignment(params) end end test "permitted attributes can be used for mass updating" do - params = ProtectedParams.new({ "a" => "b" }).permit! + params = ProtectedParams.new("a" => "b").permit! assert_equal({ "a" => "b" }, Account.new.sanitize_for_mass_assignment(params)) end test "regular attributes should still be allowed" do - assert_equal({ a: "b" }, Account.new.sanitize_for_mass_assignment(a: "b")) + assert_equal({ a: "b" }, Account.new.sanitize_for_mass_assignment(a: "b")) end end diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index c589fd2c33..4e9f43ad86 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -1,4 +1,4 @@ -require 'active_model' +require "active_model" # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true @@ -6,15 +6,15 @@ ActiveSupport::Deprecation.debug = true # Disable available locale checks to avoid warnings running the test suite. I18n.enforce_available_locales = false -require 'active_support/testing/autorun' -require 'active_support/testing/method_call_assertions' +require "active_support/testing/autorun" +require "active_support/testing/method_call_assertions" # Skips the current run on Rubinius using Minitest::Assertions#skip -def rubinius_skip(message = '') - skip message if RUBY_ENGINE == 'rbx' +def rubinius_skip(message = "") + skip message if RUBY_ENGINE == "rbx" end # Skips the current run on JRuby using Minitest::Assertions#skip -def jruby_skip(message = '') +def jruby_skip(message = "") skip message if defined?(JRUBY_VERSION) end diff --git a/activemodel/test/cases/lint_test.rb b/activemodel/test/cases/lint_test.rb index 8faf93c056..7a817d7c01 100644 --- a/activemodel/test/cases/lint_test.rb +++ b/activemodel/test/cases/lint_test.rb @@ -1,4 +1,4 @@ -require 'cases/helper' +require "cases/helper" class LintTest < ActiveModel::TestCase include ActiveModel::Lint::Tests diff --git a/activemodel/test/cases/model_test.rb b/activemodel/test/cases/model_test.rb index 3017f3541b..ba87cd1506 100644 --- a/activemodel/test/cases/model_test.rb +++ b/activemodel/test/cases/model_test.rb @@ -1,4 +1,4 @@ -require 'cases/helper' +require "cases/helper" class ModelTest < ActiveModel::TestCase include ActiveModel::Lint::Tests @@ -9,7 +9,7 @@ class ModelTest < ActiveModel::TestCase end def initialize(*args) - @attr ||= 'default value' + @attr ||= "default value" super end end @@ -50,7 +50,7 @@ class ModelTest < ActiveModel::TestCase BasicModel.new() BasicModel.new(nil) BasicModel.new({}) - SimpleModel.new(attr: 'value') + SimpleModel.new(attr: "value") end end @@ -61,17 +61,17 @@ class ModelTest < ActiveModel::TestCase def test_mixin_inclusion_chain object = BasicModel.new - assert_equal 'default value', object.attr + assert_equal "default value", object.attr end def test_mixin_initializer_when_args_exist - object = BasicModel.new(hello: 'world') - assert_equal 'world', object.hello + object = BasicModel.new(hello: "world") + assert_equal "world", object.hello end def test_mixin_initializer_when_args_dont_exist assert_raises(ActiveModel::UnknownAttributeError) do - SimpleModel.new(hello: 'world') + SimpleModel.new(hello: "world") end end end diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb index 7b8287edbf..d5cb1a62bc 100644 --- a/activemodel/test/cases/naming_test.rb +++ b/activemodel/test/cases/naming_test.rb @@ -1,8 +1,8 @@ -require 'cases/helper' -require 'models/contact' -require 'models/sheep' -require 'models/track_back' -require 'models/blog_post' +require "cases/helper" +require "models/contact" +require "models/sheep" +require "models/track_back" +require "models/blog_post" class NamingTest < ActiveModel::TestCase def setup @@ -10,31 +10,31 @@ class NamingTest < ActiveModel::TestCase end def test_singular - assert_equal 'post_track_back', @model_name.singular + assert_equal "post_track_back", @model_name.singular end def test_plural - assert_equal 'post_track_backs', @model_name.plural + assert_equal "post_track_backs", @model_name.plural end def test_element - assert_equal 'track_back', @model_name.element + assert_equal "track_back", @model_name.element end def test_collection - assert_equal 'post/track_backs', @model_name.collection + assert_equal "post/track_backs", @model_name.collection end def test_human - assert_equal 'Track back', @model_name.human + assert_equal "Track back", @model_name.human end def test_route_key - assert_equal 'post_track_backs', @model_name.route_key + assert_equal "post_track_backs", @model_name.route_key end def test_param_key - assert_equal 'post_track_back', @model_name.param_key + assert_equal "post_track_back", @model_name.param_key end def test_i18n_key @@ -48,31 +48,31 @@ class NamingWithNamespacedModelInIsolatedNamespaceTest < ActiveModel::TestCase end def test_singular - assert_equal 'blog_post', @model_name.singular + assert_equal "blog_post", @model_name.singular end def test_plural - assert_equal 'blog_posts', @model_name.plural + assert_equal "blog_posts", @model_name.plural end def test_element - assert_equal 'post', @model_name.element + assert_equal "post", @model_name.element end def test_collection - assert_equal 'blog/posts', @model_name.collection + assert_equal "blog/posts", @model_name.collection end def test_human - assert_equal 'Post', @model_name.human + assert_equal "Post", @model_name.human end def test_route_key - assert_equal 'posts', @model_name.route_key + assert_equal "posts", @model_name.route_key end def test_param_key - assert_equal 'post', @model_name.param_key + assert_equal "post", @model_name.param_key end def test_i18n_key @@ -86,31 +86,31 @@ class NamingWithNamespacedModelInSharedNamespaceTest < ActiveModel::TestCase end def test_singular - assert_equal 'blog_post', @model_name.singular + assert_equal "blog_post", @model_name.singular end def test_plural - assert_equal 'blog_posts', @model_name.plural + assert_equal "blog_posts", @model_name.plural end def test_element - assert_equal 'post', @model_name.element + assert_equal "post", @model_name.element end def test_collection - assert_equal 'blog/posts', @model_name.collection + assert_equal "blog/posts", @model_name.collection end def test_human - assert_equal 'Post', @model_name.human + assert_equal "Post", @model_name.human end def test_route_key - assert_equal 'blog_posts', @model_name.route_key + assert_equal "blog_posts", @model_name.route_key end def test_param_key - assert_equal 'blog_post', @model_name.param_key + assert_equal "blog_post", @model_name.param_key end def test_i18n_key @@ -120,35 +120,35 @@ end class NamingWithSuppliedModelNameTest < ActiveModel::TestCase def setup - @model_name = ActiveModel::Name.new(Blog::Post, nil, 'Article') + @model_name = ActiveModel::Name.new(Blog::Post, nil, "Article") end def test_singular - assert_equal 'article', @model_name.singular + assert_equal "article", @model_name.singular end def test_plural - assert_equal 'articles', @model_name.plural + assert_equal "articles", @model_name.plural end def test_element - assert_equal 'article', @model_name.element + assert_equal "article", @model_name.element end def test_collection - assert_equal 'articles', @model_name.collection + assert_equal "articles", @model_name.collection end def test_human - assert_equal 'Article', @model_name.human + assert_equal "Article", @model_name.human end def test_route_key - assert_equal 'articles', @model_name.route_key + assert_equal "articles", @model_name.route_key end def test_param_key - assert_equal 'article', @model_name.param_key + assert_equal "article", @model_name.param_key end def test_i18n_key @@ -162,31 +162,31 @@ class NamingUsingRelativeModelNameTest < ActiveModel::TestCase end def test_singular - assert_equal 'blog_post', @model_name.singular + assert_equal "blog_post", @model_name.singular end def test_plural - assert_equal 'blog_posts', @model_name.plural + assert_equal "blog_posts", @model_name.plural end def test_element - assert_equal 'post', @model_name.element + assert_equal "post", @model_name.element end def test_collection - assert_equal 'blog/posts', @model_name.collection + assert_equal "blog/posts", @model_name.collection end def test_human - assert_equal 'Post', @model_name.human + assert_equal "Post", @model_name.human end def test_route_key - assert_equal 'posts', @model_name.route_key + assert_equal "posts", @model_name.route_key end def test_param_key - assert_equal 'post', @model_name.param_key + assert_equal "post", @model_name.param_key end def test_i18n_key @@ -198,16 +198,16 @@ class NamingHelpersTest < ActiveModel::TestCase def setup @klass = Contact @record = @klass.new - @singular = 'contact' - @plural = 'contacts' + @singular = "contact" + @plural = "contacts" @uncountable = Sheep - @singular_route_key = 'contact' - @route_key = 'contacts' - @param_key = 'contact' + @singular_route_key = "contact" + @route_key = "contacts" + @param_key = "contact" end def test_to_model_called_on_record - assert_equal 'post_named_track_backs', plural(Post::TrackBack.new) + assert_equal "post_named_track_backs", plural(Post::TrackBack.new) end def test_singular diff --git a/activemodel/test/cases/railtie_test.rb b/activemodel/test/cases/railtie_test.rb index 96b3b07e50..a56b26b5ee 100644 --- a/activemodel/test/cases/railtie_test.rb +++ b/activemodel/test/cases/railtie_test.rb @@ -1,11 +1,11 @@ -require 'cases/helper' -require 'active_support/testing/isolation' +require "cases/helper" +require "active_support/testing/isolation" class RailtieTest < ActiveModel::TestCase include ActiveSupport::Testing::Isolation def setup - require 'active_model/railtie' + require "active_model/railtie" # Set a fake logger to avoid creating the log directory automatically fake_logger = Logger.new(nil) @@ -16,15 +16,15 @@ class RailtieTest < ActiveModel::TestCase end end - test 'secure password min_cost is false in the development environment' do - Rails.env = 'development' + test "secure password min_cost is false in the development environment" do + Rails.env = "development" @app.initialize! assert_equal false, ActiveModel::SecurePassword.min_cost end - test 'secure password min_cost is true in the test environment' do - Rails.env = 'test' + test "secure password min_cost is true in the test environment" do + Rails.env = "test" @app.initialize! assert_equal true, ActiveModel::SecurePassword.min_cost diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb index 6d56c8344a..77ce86f392 100644 --- a/activemodel/test/cases/secure_password_test.rb +++ b/activemodel/test/cases/secure_password_test.rb @@ -1,6 +1,6 @@ -require 'cases/helper' -require 'models/user' -require 'models/visitor' +require "cases/helper" +require "models/user" +require "models/visitor" class SecurePasswordTest < ActiveModel::TestCase setup do @@ -13,7 +13,7 @@ class SecurePasswordTest < ActiveModel::TestCase # Simulate loading an existing user from the DB @existing_user = User.new - @existing_user.password_digest = BCrypt::Password.create('password', cost: BCrypt::Engine::MIN_COST) + @existing_user.password_digest = BCrypt::Password.create("password", cost: BCrypt::Engine::MIN_COST) end teardown do @@ -29,157 +29,157 @@ class SecurePasswordTest < ActiveModel::TestCase end test "create a new user with validations and valid password/confirmation" do - @user.password = 'password' - @user.password_confirmation = 'password' + @user.password = "password" + @user.password_confirmation = "password" - assert @user.valid?(:create), 'user should be valid' + assert @user.valid?(:create), "user should be valid" - @user.password = 'a' * 72 - @user.password_confirmation = 'a' * 72 + @user.password = "a" * 72 + @user.password_confirmation = "a" * 72 - assert @user.valid?(:create), 'user should be valid' + assert @user.valid?(:create), "user should be valid" end test "create a new user with validation and a spaces only password" do - @user.password = ' ' * 72 - assert @user.valid?(:create), 'user should be valid' + @user.password = " " * 72 + assert @user.valid?(:create), "user should be valid" end test "create a new user with validation and a blank password" do - @user.password = '' - assert !@user.valid?(:create), 'user should be invalid' + @user.password = "" + assert !@user.valid?(:create), "user should be invalid" assert_equal 1, @user.errors.count assert_equal ["can't be blank"], @user.errors[:password] end test "create a new user with validation and a nil password" do @user.password = nil - assert !@user.valid?(:create), 'user should be invalid' + assert !@user.valid?(:create), "user should be invalid" assert_equal 1, @user.errors.count assert_equal ["can't be blank"], @user.errors[:password] end - test 'create a new user with validation and password length greater than 72' do - @user.password = 'a' * 73 - @user.password_confirmation = 'a' * 73 - assert !@user.valid?(:create), 'user should be invalid' + test "create a new user with validation and password length greater than 72" do + @user.password = "a" * 73 + @user.password_confirmation = "a" * 73 + assert !@user.valid?(:create), "user should be invalid" assert_equal 1, @user.errors.count assert_equal ["is too long (maximum is 72 characters)"], @user.errors[:password] end test "create a new user with validation and a blank password confirmation" do - @user.password = 'password' - @user.password_confirmation = '' - assert !@user.valid?(:create), 'user should be invalid' + @user.password = "password" + @user.password_confirmation = "" + assert !@user.valid?(:create), "user should be invalid" assert_equal 1, @user.errors.count assert_equal ["doesn't match Password"], @user.errors[:password_confirmation] end test "create a new user with validation and a nil password confirmation" do - @user.password = 'password' + @user.password = "password" @user.password_confirmation = nil - assert @user.valid?(:create), 'user should be valid' + assert @user.valid?(:create), "user should be valid" end test "create a new user with validation and an incorrect password confirmation" do - @user.password = 'password' - @user.password_confirmation = 'something else' - assert !@user.valid?(:create), 'user should be invalid' + @user.password = "password" + @user.password_confirmation = "something else" + assert !@user.valid?(:create), "user should be invalid" assert_equal 1, @user.errors.count assert_equal ["doesn't match Password"], @user.errors[:password_confirmation] end test "update an existing user with validation and no change in password" do - assert @existing_user.valid?(:update), 'user should be valid' + assert @existing_user.valid?(:update), "user should be valid" end test "update an existing user with validations and valid password/confirmation" do - @existing_user.password = 'password' - @existing_user.password_confirmation = 'password' + @existing_user.password = "password" + @existing_user.password_confirmation = "password" - assert @existing_user.valid?(:update), 'user should be valid' + assert @existing_user.valid?(:update), "user should be valid" - @existing_user.password = 'a' * 72 - @existing_user.password_confirmation = 'a' * 72 + @existing_user.password = "a" * 72 + @existing_user.password_confirmation = "a" * 72 - assert @existing_user.valid?(:update), 'user should be valid' + assert @existing_user.valid?(:update), "user should be valid" end test "updating an existing user with validation and a blank password" do - @existing_user.password = '' - assert @existing_user.valid?(:update), 'user should be valid' + @existing_user.password = "" + assert @existing_user.valid?(:update), "user should be valid" end test "updating an existing user with validation and a spaces only password" do - @user.password = ' ' * 72 - assert @user.valid?(:update), 'user should be valid' + @user.password = " " * 72 + assert @user.valid?(:update), "user should be valid" end test "updating an existing user with validation and a blank password and password_confirmation" do - @existing_user.password = '' - @existing_user.password_confirmation = '' - assert @existing_user.valid?(:update), 'user should be valid' + @existing_user.password = "" + @existing_user.password_confirmation = "" + assert @existing_user.valid?(:update), "user should be valid" end test "updating an existing user with validation and a nil password" do @existing_user.password = nil - assert !@existing_user.valid?(:update), 'user should be invalid' + assert !@existing_user.valid?(:update), "user should be invalid" assert_equal 1, @existing_user.errors.count assert_equal ["can't be blank"], @existing_user.errors[:password] end - test 'updating an existing user with validation and password length greater than 72' do - @existing_user.password = 'a' * 73 - @existing_user.password_confirmation = 'a' * 73 - assert !@existing_user.valid?(:update), 'user should be invalid' + test "updating an existing user with validation and password length greater than 72" do + @existing_user.password = "a" * 73 + @existing_user.password_confirmation = "a" * 73 + assert !@existing_user.valid?(:update), "user should be invalid" assert_equal 1, @existing_user.errors.count assert_equal ["is too long (maximum is 72 characters)"], @existing_user.errors[:password] end test "updating an existing user with validation and a blank password confirmation" do - @existing_user.password = 'password' - @existing_user.password_confirmation = '' - assert !@existing_user.valid?(:update), 'user should be invalid' + @existing_user.password = "password" + @existing_user.password_confirmation = "" + assert !@existing_user.valid?(:update), "user should be invalid" assert_equal 1, @existing_user.errors.count assert_equal ["doesn't match Password"], @existing_user.errors[:password_confirmation] end test "updating an existing user with validation and a nil password confirmation" do - @existing_user.password = 'password' + @existing_user.password = "password" @existing_user.password_confirmation = nil - assert @existing_user.valid?(:update), 'user should be valid' + assert @existing_user.valid?(:update), "user should be valid" end test "updating an existing user with validation and an incorrect password confirmation" do - @existing_user.password = 'password' - @existing_user.password_confirmation = 'something else' - assert !@existing_user.valid?(:update), 'user should be invalid' + @existing_user.password = "password" + @existing_user.password_confirmation = "something else" + assert !@existing_user.valid?(:update), "user should be invalid" assert_equal 1, @existing_user.errors.count assert_equal ["doesn't match Password"], @existing_user.errors[:password_confirmation] end test "updating an existing user with validation and a blank password digest" do - @existing_user.password_digest = '' - assert !@existing_user.valid?(:update), 'user should be invalid' + @existing_user.password_digest = "" + assert !@existing_user.valid?(:update), "user should be invalid" assert_equal 1, @existing_user.errors.count assert_equal ["can't be blank"], @existing_user.errors[:password] end test "updating an existing user with validation and a nil password digest" do @existing_user.password_digest = nil - assert !@existing_user.valid?(:update), 'user should be invalid' + assert !@existing_user.valid?(:update), "user should be invalid" assert_equal 1, @existing_user.errors.count assert_equal ["can't be blank"], @existing_user.errors[:password] end test "setting a blank password should not change an existing password" do - @existing_user.password = '' - assert @existing_user.password_digest == 'password' + @existing_user.password = "" + assert @existing_user.password_digest == "password" end test "setting a nil password should clear an existing password" do @existing_user.password = nil - assert_equal nil, @existing_user.password_digest + assert_nil @existing_user.password_digest end test "authenticate" do diff --git a/activemodel/test/cases/serialization_test.rb b/activemodel/test/cases/serialization_test.rb index 8d3165cd78..f78efd2f0c 100644 --- a/activemodel/test/cases/serialization_test.rb +++ b/activemodel/test/cases/serialization_test.rb @@ -1,5 +1,5 @@ require "cases/helper" -require 'active_support/core_ext/object/instance_variables' +require "active_support/core_ext/object/instance_variables" class SerializationTest < ActiveModel::TestCase class User @@ -18,14 +18,14 @@ class SerializationTest < ActiveModel::TestCase def method_missing(method_name, *args) if method_name == :bar - 'i_am_bar' + "i_am_bar" else super end end def foo - 'i_am_foo' + "i_am_foo" end end @@ -40,43 +40,43 @@ class SerializationTest < ActiveModel::TestCase end setup do - @user = User.new('David', 'david@example.com', 'male') + @user = User.new("David", "david@example.com", "male") @user.address = Address.new @user.address.street = "123 Lane" @user.address.city = "Springfield" @user.address.state = "CA" @user.address.zip = 11111 - @user.friends = [User.new('Joe', 'joe@example.com', 'male'), - User.new('Sue', 'sue@example.com', 'female')] + @user.friends = [User.new("Joe", "joe@example.com", "male"), + User.new("Sue", "sue@example.com", "female")] end def test_method_serializable_hash_should_work - expected = {"name"=>"David", "gender"=>"male", "email"=>"david@example.com"} + expected = { "name" => "David", "gender" => "male", "email" => "david@example.com" } assert_equal expected, @user.serializable_hash end def test_method_serializable_hash_should_work_with_only_option - expected = {"name"=>"David"} + expected = { "name" => "David" } assert_equal expected, @user.serializable_hash(only: [:name]) end def test_method_serializable_hash_should_work_with_except_option - expected = {"gender"=>"male", "email"=>"david@example.com"} + expected = { "gender" => "male", "email" => "david@example.com" } assert_equal expected, @user.serializable_hash(except: [:name]) end def test_method_serializable_hash_should_work_with_methods_option - expected = {"name"=>"David", "gender"=>"male", "foo"=>"i_am_foo", "bar"=>"i_am_bar", "email"=>"david@example.com"} + expected = { "name" => "David", "gender" => "male", "foo" => "i_am_foo", "bar" => "i_am_bar", "email" => "david@example.com" } assert_equal expected, @user.serializable_hash(methods: [:foo, :bar]) end def test_method_serializable_hash_should_work_with_only_and_methods - expected = {"foo"=>"i_am_foo", "bar"=>"i_am_bar"} + expected = { "foo" => "i_am_foo", "bar" => "i_am_bar" } assert_equal expected, @user.serializable_hash(only: [], methods: [:foo, :bar]) end def test_method_serializable_hash_should_work_with_except_and_methods - expected = {"gender"=>"male", "foo"=>"i_am_foo", "bar"=>"i_am_bar"} + expected = { "gender" => "male", "foo" => "i_am_foo", "bar" => "i_am_bar" } assert_equal expected, @user.serializable_hash(except: [:name, :email], methods: [:foo, :bar]) end @@ -94,21 +94,21 @@ class SerializationTest < ActiveModel::TestCase end def test_include_option_with_singular_association - expected = {"name"=>"David", "gender"=>"male", "email"=>"david@example.com", - "address"=>{"street"=>"123 Lane", "city"=>"Springfield", "state"=>"CA", "zip"=>11111}} + expected = { "name" => "David", "gender" => "male", "email" => "david@example.com", + "address" => { "street" => "123 Lane", "city" => "Springfield", "state" => "CA", "zip" => 11111 } } assert_equal expected, @user.serializable_hash(include: :address) end def test_include_option_with_plural_association - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", - "friends"=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'}, - {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]} + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", + "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" }, + { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] } assert_equal expected, @user.serializable_hash(include: :friends) end def test_include_option_with_empty_association @user.friends = [] - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", "friends"=>[]} + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", "friends" => [] } assert_equal expected, @user.serializable_hash(include: :friends) end @@ -124,52 +124,52 @@ class SerializationTest < ActiveModel::TestCase def test_include_option_with_ary @user.friends = FriendList.new(@user.friends) - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", - "friends"=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'}, - {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]} + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", + "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" }, + { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] } assert_equal expected, @user.serializable_hash(include: :friends) end def test_multiple_includes - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", - "address"=>{"street"=>"123 Lane", "city"=>"Springfield", "state"=>"CA", "zip"=>11111}, - "friends"=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'}, - {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]} + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", + "address" => { "street" => "123 Lane", "city" => "Springfield", "state" => "CA", "zip" => 11111 }, + "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" }, + { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] } assert_equal expected, @user.serializable_hash(include: [:address, :friends]) end def test_include_with_options - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", - "address"=>{"street"=>"123 Lane"}} + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", + "address" => { "street" => "123 Lane" } } assert_equal expected, @user.serializable_hash(include: { address: { only: "street" } }) end def test_nested_include @user.friends.first.friends = [@user] - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", - "friends"=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male', - "friends"=> [{"email"=>"david@example.com", "gender"=>"male", "name"=>"David"}]}, - {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female', "friends"=> []}]} + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", + "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male", + "friends" => [{ "email" => "david@example.com", "gender" => "male", "name" => "David" }] }, + { "name" => "Sue", "email" => "sue@example.com", "gender" => "female", "friends" => [] }] } assert_equal expected, @user.serializable_hash(include: { friends: { include: :friends } }) end def test_only_include - expected = {"name"=>"David", "friends" => [{"name" => "Joe"}, {"name" => "Sue"}]} + expected = { "name" => "David", "friends" => [{ "name" => "Joe" }, { "name" => "Sue" }] } assert_equal expected, @user.serializable_hash(only: :name, include: { friends: { only: :name } }) end def test_except_include - expected = {"name"=>"David", "email"=>"david@example.com", - "friends"=> [{"name" => 'Joe', "email" => 'joe@example.com'}, - {"name" => "Sue", "email" => 'sue@example.com'}]} + expected = { "name" => "David", "email" => "david@example.com", + "friends" => [{ "name" => "Joe", "email" => "joe@example.com" }, + { "name" => "Sue", "email" => "sue@example.com" }] } assert_equal expected, @user.serializable_hash(except: :gender, include: { friends: { except: :gender } }) end def test_multiple_includes_with_options - expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", - "address"=>{"street"=>"123 Lane"}, - "friends"=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'}, - {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]} - assert_equal expected, @user.serializable_hash(include: [{ address: {only: "street" } }, :friends]) + expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", + "address" => { "street" => "123 Lane" }, + "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" }, + { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] } + assert_equal expected, @user.serializable_hash(include: [{ address: { only: "street" } }, :friends]) end end diff --git a/activemodel/test/cases/serializers/json_serialization_test.rb b/activemodel/test/cases/serializers/json_serialization_test.rb index d765a47636..d15ba64eb0 100644 --- a/activemodel/test/cases/serializers/json_serialization_test.rb +++ b/activemodel/test/cases/serializers/json_serialization_test.rb @@ -1,15 +1,15 @@ -require 'cases/helper' -require 'models/contact' -require 'active_support/core_ext/object/instance_variables' +require "cases/helper" +require "models/contact" +require "active_support/core_ext/object/instance_variables" class JsonSerializationTest < ActiveModel::TestCase def setup @contact = Contact.new - @contact.name = 'Konata Izumi' + @contact.name = "Konata Izumi" @contact.age = 16 @contact.created_at = Time.utc(2006, 8, 1) @contact.awesome = true - @contact.preferences = { 'shows' => 'anime' } + @contact.preferences = { "shows" => "anime" } end test "should not include root in json (class method)" do @@ -18,7 +18,7 @@ class JsonSerializationTest < ActiveModel::TestCase assert_no_match %r{^\{"contact":\{}, json assert_match %r{"name":"Konata Izumi"}, json assert_match %r{"age":16}, json - assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_includes json, %("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}) assert_match %r{"awesome":true}, json assert_match %r{"preferences":\{"shows":"anime"\}}, json end @@ -32,7 +32,7 @@ class JsonSerializationTest < ActiveModel::TestCase assert_match %r{^\{"contact":\{}, json assert_match %r{"name":"Konata Izumi"}, json assert_match %r{"age":16}, json - assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_includes json, %("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}) assert_match %r{"awesome":true}, json assert_match %r{"preferences":\{"shows":"anime"\}}, json ensure @@ -53,12 +53,12 @@ class JsonSerializationTest < ActiveModel::TestCase end test "should include custom root in json" do - json = @contact.to_json(root: 'json_contact') + json = @contact.to_json(root: "json_contact") assert_match %r{^\{"json_contact":\{}, json assert_match %r{"name":"Konata Izumi"}, json assert_match %r{"age":16}, json - assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_includes json, %("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}) assert_match %r{"awesome":true}, json assert_match %r{"preferences":\{"shows":"anime"\}}, json end @@ -68,7 +68,7 @@ class JsonSerializationTest < ActiveModel::TestCase assert_match %r{"name":"Konata Izumi"}, json assert_match %r{"age":16}, json - assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_includes json, %("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}) assert_match %r{"awesome":true}, json assert_match %r{"preferences":\{"shows":"anime"\}}, json end @@ -79,7 +79,7 @@ class JsonSerializationTest < ActiveModel::TestCase assert_match %r{"name":"Konata Izumi"}, json assert_match %r{"age":16}, json assert_no_match %r{"awesome":true}, json - assert !json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_not_includes json, %("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}) assert_no_match %r{"preferences":\{"shows":"anime"\}}, json end @@ -89,7 +89,7 @@ class JsonSerializationTest < ActiveModel::TestCase assert_no_match %r{"name":"Konata Izumi"}, json assert_no_match %r{"age":16}, json assert_match %r{"awesome":true}, json - assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_includes json, %("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}) assert_match %r{"preferences":\{"shows":"anime"\}}, json end @@ -134,9 +134,9 @@ class JsonSerializationTest < ActiveModel::TestCase json = @contact.as_json assert_kind_of Hash, json - assert_kind_of Hash, json['contact'] + assert_kind_of Hash, json["contact"] %w(name age created_at awesome preferences).each do |field| - assert_equal @contact.send(field), json['contact'][field] + assert_equal @contact.send(field), json["contact"][field] end ensure Contact.include_root_in_json = original_include_root_in_json diff --git a/activemodel/test/cases/translation_test.rb b/activemodel/test/cases/translation_test.rb index 2c89388f14..9972f9daea 100644 --- a/activemodel/test/cases/translation_test.rb +++ b/activemodel/test/cases/translation_test.rb @@ -1,8 +1,7 @@ -require 'cases/helper' -require 'models/person' +require "cases/helper" +require "models/person" class ActiveModelI18nTests < ActiveModel::TestCase - def setup I18n.backend = I18n::Backend::Simple.new end @@ -12,102 +11,101 @@ class ActiveModelI18nTests < ActiveModel::TestCase end def test_translated_model_attributes - I18n.backend.store_translations 'en', activemodel: { attributes: { person: { name: 'person name attribute' } } } - assert_equal 'person name attribute', Person.human_attribute_name('name') + I18n.backend.store_translations "en", activemodel: { attributes: { person: { name: "person name attribute" } } } + assert_equal "person name attribute", Person.human_attribute_name("name") end def test_translated_model_attributes_with_default - I18n.backend.store_translations 'en', attributes: { name: 'name default attribute' } - assert_equal 'name default attribute', Person.human_attribute_name('name') + I18n.backend.store_translations "en", attributes: { name: "name default attribute" } + assert_equal "name default attribute", Person.human_attribute_name("name") end def test_translated_model_attributes_using_default_option - assert_equal 'name default attribute', Person.human_attribute_name('name', default: "name default attribute") + assert_equal "name default attribute", Person.human_attribute_name("name", default: "name default attribute") end def test_translated_model_attributes_using_default_option_as_symbol - I18n.backend.store_translations 'en', default_name: 'name default attribute' - assert_equal 'name default attribute', Person.human_attribute_name('name', default: :default_name) + I18n.backend.store_translations "en", default_name: "name default attribute" + assert_equal "name default attribute", Person.human_attribute_name("name", default: :default_name) end def test_translated_model_attributes_falling_back_to_default - assert_equal 'Name', Person.human_attribute_name('name') + assert_equal "Name", Person.human_attribute_name("name") end def test_translated_model_attributes_using_default_option_as_symbol_and_falling_back_to_default - assert_equal 'Name', Person.human_attribute_name('name', default: :default_name) + assert_equal "Name", Person.human_attribute_name("name", default: :default_name) end def test_translated_model_attributes_with_symbols - I18n.backend.store_translations 'en', activemodel: { attributes: { person: { name: 'person name attribute'} } } - assert_equal 'person name attribute', Person.human_attribute_name(:name) + I18n.backend.store_translations "en", activemodel: { attributes: { person: { name: "person name attribute" } } } + assert_equal "person name attribute", Person.human_attribute_name(:name) end def test_translated_model_attributes_with_ancestor - I18n.backend.store_translations 'en', activemodel: { attributes: { child: { name: 'child name attribute'} } } - assert_equal 'child name attribute', Child.human_attribute_name('name') + I18n.backend.store_translations "en", activemodel: { attributes: { child: { name: "child name attribute" } } } + assert_equal "child name attribute", Child.human_attribute_name("name") end def test_translated_model_attributes_with_ancestors_fallback - I18n.backend.store_translations 'en', activemodel: { attributes: { person: { name: 'person name attribute'} } } - assert_equal 'person name attribute', Child.human_attribute_name('name') + I18n.backend.store_translations "en", activemodel: { attributes: { person: { name: "person name attribute" } } } + assert_equal "person name attribute", Child.human_attribute_name("name") end def test_translated_model_attributes_with_attribute_matching_namespaced_model_name - I18n.backend.store_translations 'en', activemodel: { attributes: { - person: { gender: 'person gender'}, - :"person/gender" => { attribute: 'person gender attribute' } + I18n.backend.store_translations "en", activemodel: { attributes: { + person: { gender: "person gender" }, + "person/gender": { attribute: "person gender attribute" } } } - assert_equal 'person gender', Person.human_attribute_name('gender') - assert_equal 'person gender attribute', Person::Gender.human_attribute_name('attribute') + assert_equal "person gender", Person.human_attribute_name("gender") + assert_equal "person gender attribute", Person::Gender.human_attribute_name("attribute") end def test_translated_deeply_nested_model_attributes - I18n.backend.store_translations 'en', activemodel: { attributes: { :"person/contacts/addresses" => { street: 'Deeply Nested Address Street' } } } - assert_equal 'Deeply Nested Address Street', Person.human_attribute_name('contacts.addresses.street') + I18n.backend.store_translations "en", activemodel: { attributes: { "person/contacts/addresses": { street: "Deeply Nested Address Street" } } } + assert_equal "Deeply Nested Address Street", Person.human_attribute_name("contacts.addresses.street") end def test_translated_nested_model_attributes - I18n.backend.store_translations 'en', activemodel: { attributes: { :"person/addresses" => { street: 'Person Address Street' } } } - assert_equal 'Person Address Street', Person.human_attribute_name('addresses.street') + I18n.backend.store_translations "en", activemodel: { attributes: { "person/addresses": { street: "Person Address Street" } } } + assert_equal "Person Address Street", Person.human_attribute_name("addresses.street") end def test_translated_nested_model_attributes_with_namespace_fallback - I18n.backend.store_translations 'en', activemodel: { attributes: { addresses: { street: 'Cool Address Street' } } } - assert_equal 'Cool Address Street', Person.human_attribute_name('addresses.street') + I18n.backend.store_translations "en", activemodel: { attributes: { addresses: { street: "Cool Address Street" } } } + assert_equal "Cool Address Street", Person.human_attribute_name("addresses.street") end def test_translated_model_names - I18n.backend.store_translations 'en', activemodel: { models: { person: 'person model' } } - assert_equal 'person model', Person.model_name.human + I18n.backend.store_translations "en", activemodel: { models: { person: "person model" } } + assert_equal "person model", Person.model_name.human end def test_translated_model_names_with_sti - I18n.backend.store_translations 'en', activemodel: { models: { child: 'child model' } } - assert_equal 'child model', Child.model_name.human + I18n.backend.store_translations "en", activemodel: { models: { child: "child model" } } + assert_equal "child model", Child.model_name.human end def test_translated_model_with_namespace - I18n.backend.store_translations 'en', activemodel: { models: { 'person/gender': 'gender model' } } - assert_equal 'gender model', Person::Gender.model_name.human + I18n.backend.store_translations "en", activemodel: { models: { 'person/gender': "gender model" } } + assert_equal "gender model", Person::Gender.model_name.human end def test_translated_model_names_with_ancestors_fallback - I18n.backend.store_translations 'en', activemodel: { models: { person: 'person model' } } - assert_equal 'person model', Child.model_name.human + I18n.backend.store_translations "en", activemodel: { models: { person: "person model" } } + assert_equal "person model", Child.model_name.human end def test_human_does_not_modify_options - options = { default: 'person model' } + options = { default: "person model" } Person.model_name.human(options) - assert_equal({ default: 'person model' }, options) + assert_equal({ default: "person model" }, options) end def test_human_attribute_name_does_not_modify_options - options = { default: 'Cool gender' } - Person.human_attribute_name('gender', options) - assert_equal({ default: 'Cool gender' }, options) + options = { default: "Cool gender" } + Person.human_attribute_name("gender", options) + assert_equal({ default: "Cool gender" }, options) end end - diff --git a/activemodel/test/cases/type/big_integer_test.rb b/activemodel/test/cases/type/big_integer_test.rb new file mode 100644 index 0000000000..56002b7cc6 --- /dev/null +++ b/activemodel/test/cases/type/big_integer_test.rb @@ -0,0 +1,24 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class BigIntegerTest < ActiveModel::TestCase + def test_type_cast_big_integer + type = Type::BigInteger.new + assert_equal 1, type.cast(1) + assert_equal 1, type.cast("1") + end + + def test_small_values + type = Type::BigInteger.new + assert_equal(-9999999999999999999999999999999, type.serialize(-9999999999999999999999999999999)) + end + + def test_large_values + type = Type::BigInteger.new + assert_equal 9999999999999999999999999999999, type.serialize(9999999999999999999999999999999) + end + end + end +end diff --git a/activemodel/test/cases/type/binary_test.rb b/activemodel/test/cases/type/binary_test.rb new file mode 100644 index 0000000000..e9c2ccfca4 --- /dev/null +++ b/activemodel/test/cases/type/binary_test.rb @@ -0,0 +1,15 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class BinaryTest < ActiveModel::TestCase + def test_type_cast_binary + type = Type::Binary.new + assert_nil type.cast(nil) + assert_equal "1", type.cast("1") + assert_equal 1, type.cast(1) + end + end + end +end diff --git a/activemodel/test/cases/type/boolean_test.rb b/activemodel/test/cases/type/boolean_test.rb new file mode 100644 index 0000000000..92e5aebfb7 --- /dev/null +++ b/activemodel/test/cases/type/boolean_test.rb @@ -0,0 +1,39 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class BooleanTest < ActiveModel::TestCase + def test_type_cast_boolean + type = Type::Boolean.new + assert type.cast("").nil? + assert type.cast(nil).nil? + + assert type.cast(true) + assert type.cast(1) + assert type.cast("1") + assert type.cast("t") + assert type.cast("T") + assert type.cast("true") + assert type.cast("TRUE") + assert type.cast("on") + assert type.cast("ON") + assert type.cast(" ") + assert type.cast("\u3000\r\n") + assert type.cast("\u0000") + assert type.cast("SOMETHING RANDOM") + + # explicitly check for false vs nil + assert_equal false, type.cast(false) + assert_equal false, type.cast(0) + assert_equal false, type.cast("0") + assert_equal false, type.cast("f") + assert_equal false, type.cast("F") + assert_equal false, type.cast("false") + assert_equal false, type.cast("FALSE") + assert_equal false, type.cast("off") + assert_equal false, type.cast("OFF") + end + end + end +end diff --git a/activemodel/test/cases/type/date_test.rb b/activemodel/test/cases/type/date_test.rb new file mode 100644 index 0000000000..0cc90e99d3 --- /dev/null +++ b/activemodel/test/cases/type/date_test.rb @@ -0,0 +1,19 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class DateTest < ActiveModel::TestCase + def test_type_cast_date + type = Type::Date.new + assert_nil type.cast(nil) + assert_nil type.cast("") + assert_nil type.cast(" ") + assert_nil type.cast("ABC") + + date_string = ::Time.now.utc.strftime("%F") + assert_equal date_string, type.cast(date_string).strftime("%F") + end + end + end +end diff --git a/activemodel/test/cases/type/date_time_test.rb b/activemodel/test/cases/type/date_time_test.rb new file mode 100644 index 0000000000..75a7fc686e --- /dev/null +++ b/activemodel/test/cases/type/date_time_test.rb @@ -0,0 +1,38 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class DateTimeTest < ActiveModel::TestCase + def test_type_cast_datetime_and_timestamp + type = Type::DateTime.new + assert_nil type.cast(nil) + assert_nil type.cast("") + assert_nil type.cast(" ") + assert_nil type.cast("ABC") + + datetime_string = ::Time.now.utc.strftime("%FT%T") + assert_equal datetime_string, type.cast(datetime_string).strftime("%FT%T") + end + + def test_string_to_time_with_timezone + ["UTC", "US/Eastern"].each do |zone| + with_timezone_config default: zone do + type = Type::DateTime.new + assert_equal ::Time.utc(2013, 9, 4, 0, 0, 0), type.cast("Wed, 04 Sep 2013 03:00:00 EAT") + end + end + end + + private + + def with_timezone_config(default:) + old_zone_default = ::Time.zone_default + ::Time.zone_default = ::Time.find_zone(default) + yield + ensure + ::Time.zone_default = old_zone_default + end + end + end +end diff --git a/activemodel/test/cases/type/decimal_test.rb b/activemodel/test/cases/type/decimal_test.rb index 1950566c0e..46a913258e 100644 --- a/activemodel/test/cases/type/decimal_test.rb +++ b/activemodel/test/cases/type/decimal_test.rb @@ -48,9 +48,9 @@ module ActiveModel def test_changed? type = Decimal.new - assert type.changed?(5.0, 5.0, '5.0wibble') - assert_not type.changed?(5.0, 5.0, '5.0') - assert_not type.changed?(-5.0, -5.0, '-5.0') + assert type.changed?(5.0, 5.0, "5.0wibble") + assert_not type.changed?(5.0, 5.0, "5.0") + assert_not type.changed?(-5.0, -5.0, "-5.0") end def test_scale_is_applied_before_precision_to_prevent_rounding_errors diff --git a/activemodel/test/cases/type/float_test.rb b/activemodel/test/cases/type/float_test.rb new file mode 100644 index 0000000000..2e34f57f7e --- /dev/null +++ b/activemodel/test/cases/type/float_test.rb @@ -0,0 +1,22 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class FloatTest < ActiveModel::TestCase + def test_type_cast_float + type = Type::Float.new + assert_equal 1.0, type.cast("1") + end + + def test_changing_float + type = Type::Float.new + + assert type.changed?(5.0, 5.0, "5wibble") + assert_not type.changed?(5.0, 5.0, "5") + assert_not type.changed?(5.0, 5.0, "5.0") + assert_not type.changed?(nil, nil, nil) + end + end + end +end diff --git a/activemodel/test/cases/type/immutable_string_test.rb b/activemodel/test/cases/type/immutable_string_test.rb new file mode 100644 index 0000000000..23e58974fb --- /dev/null +++ b/activemodel/test/cases/type/immutable_string_test.rb @@ -0,0 +1,21 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class ImmutableStringTest < ActiveModel::TestCase + test "cast strings are frozen" do + s = "foo" + type = Type::ImmutableString.new + assert_equal true, type.cast(s).frozen? + end + + test "immutable strings are not duped coming out" do + s = "foo" + type = Type::ImmutableString.new + assert_same s, type.cast(s) + assert_same s, type.deserialize(s) + end + end + end +end diff --git a/activemodel/test/cases/type/integer_test.rb b/activemodel/test/cases/type/integer_test.rb index 6603f25c9a..2b9b03f3cf 100644 --- a/activemodel/test/cases/type/integer_test.rb +++ b/activemodel/test/cases/type/integer_test.rb @@ -1,5 +1,6 @@ require "cases/helper" require "active_model/type" +require "active_support/core_ext/numeric/time" module ActiveModel module Type @@ -7,10 +8,10 @@ module ActiveModel test "simple values" do type = Type::Integer.new assert_equal 1, type.cast(1) - assert_equal 1, type.cast('1') - assert_equal 1, type.cast('1ignore') - assert_equal 0, type.cast('bad1') - assert_equal 0, type.cast('bad') + assert_equal 1, type.cast("1") + assert_equal 1, type.cast("1ignore") + assert_equal 0, type.cast("bad1") + assert_equal 0, type.cast("bad") assert_equal 1, type.cast(1.7) assert_equal 0, type.cast(false) assert_equal 1, type.cast(true) @@ -19,8 +20,8 @@ module ActiveModel test "random objects cast to nil" do type = Type::Integer.new - assert_nil type.cast([1,2]) - assert_nil type.cast({1 => 2}) + assert_nil type.cast([1, 2]) + assert_nil type.cast(1 => 2) assert_nil type.cast(1..2) end @@ -32,7 +33,7 @@ module ActiveModel test "casting nan and infinity" do type = Type::Integer.new assert_nil type.cast(::Float::NAN) - assert_nil type.cast(1.0/0.0) + assert_nil type.cast(1.0 / 0.0) end test "casting booleans for database" do @@ -41,14 +42,20 @@ module ActiveModel assert_equal 0, type.serialize(false) end + test "casting duration" do + type = Type::Integer.new + assert_equal 1800, type.cast(30.minutes) + assert_equal 7200, type.cast(2.hours) + end + test "changed?" do type = Type::Integer.new - assert type.changed?(5, 5, '5wibble') - assert_not type.changed?(5, 5, '5') - assert_not type.changed?(5, 5, '5.0') - assert_not type.changed?(-5, -5, '-5') - assert_not type.changed?(-5, -5, '-5.0') + assert type.changed?(5, 5, "5wibble") + assert_not type.changed?(5, 5, "5") + assert_not type.changed?(5, 5, "5.0") + assert_not type.changed?(-5, -5, "-5") + assert_not type.changed?(-5, -5, "-5.0") assert_not type.changed?(nil, nil, nil) end diff --git a/activemodel/test/cases/type/registry_test.rb b/activemodel/test/cases/type/registry_test.rb index 2a48998a62..927b6d0307 100644 --- a/activemodel/test/cases/type/registry_test.rb +++ b/activemodel/test/cases/type/registry_test.rb @@ -2,38 +2,40 @@ require "cases/helper" require "active_model/type" module ActiveModel - class RegistryTest < ActiveModel::TestCase - test "a class can be registered for a symbol" do - registry = Type::Registry.new - registry.register(:foo, ::String) - registry.register(:bar, ::Array) + module Type + class RegistryTest < ActiveModel::TestCase + test "a class can be registered for a symbol" do + registry = Type::Registry.new + registry.register(:foo, ::String) + registry.register(:bar, ::Array) - assert_equal "", registry.lookup(:foo) - assert_equal [], registry.lookup(:bar) - end - - test "a block can be registered" do - registry = Type::Registry.new - registry.register(:foo) do |*args| - [*args, "block for foo"] + assert_equal "", registry.lookup(:foo) + assert_equal [], registry.lookup(:bar) end - registry.register(:bar) do |*args| - [*args, "block for bar"] + + test "a block can be registered" do + registry = Type::Registry.new + registry.register(:foo) do |*args| + [*args, "block for foo"] + end + registry.register(:bar) do |*args| + [*args, "block for bar"] + end + + assert_equal [:foo, 1, "block for foo"], registry.lookup(:foo, 1) + assert_equal [:foo, 2, "block for foo"], registry.lookup(:foo, 2) + assert_equal [:bar, 1, 2, 3, "block for bar"], registry.lookup(:bar, 1, 2, 3) end - assert_equal [:foo, 1, "block for foo"], registry.lookup(:foo, 1) - assert_equal [:foo, 2, "block for foo"], registry.lookup(:foo, 2) - assert_equal [:bar, 1, 2, 3, "block for bar"], registry.lookup(:bar, 1, 2, 3) - end + test "a reasonable error is given when no type is found" do + registry = Type::Registry.new - test "a reasonable error is given when no type is found" do - registry = Type::Registry.new + e = assert_raises(ArgumentError) do + registry.lookup(:foo) + end - e = assert_raises(ArgumentError) do - registry.lookup(:foo) + assert_equal "Unknown type :foo", e.message end - - assert_equal "Unknown type :foo", e.message end end end diff --git a/activemodel/test/cases/type/string_test.rb b/activemodel/test/cases/type/string_test.rb index 7b25a1ef74..222083817e 100644 --- a/activemodel/test/cases/type/string_test.rb +++ b/activemodel/test/cases/type/string_test.rb @@ -2,26 +2,27 @@ require "cases/helper" require "active_model/type" module ActiveModel - class StringTypeTest < ActiveModel::TestCase - test "type casting" do - type = Type::String.new - assert_equal "t", type.cast(true) - assert_equal "f", type.cast(false) - assert_equal "123", type.cast(123) - end + module Type + class StringTest < ActiveModel::TestCase + test "type casting" do + type = Type::String.new + assert_equal "t", type.cast(true) + assert_equal "f", type.cast(false) + assert_equal "123", type.cast(123) + end - test "immutable strings are not duped coming out" do - s = "foo" - type = Type::ImmutableString.new - assert_same s, type.cast(s) - assert_same s, type.deserialize(s) - end + test "cast strings are mutable" do + s = "foo" + type = Type::String.new + assert_equal false, type.cast(s).frozen? + end - test "values are duped coming out" do - s = "foo" - type = Type::String.new - assert_not_same s, type.cast(s) - assert_not_same s, type.deserialize(s) + test "values are duped coming out" do + s = "foo" + type = Type::String.new + assert_not_same s, type.cast(s) + assert_not_same s, type.deserialize(s) + end end end end diff --git a/activemodel/test/cases/type/time_test.rb b/activemodel/test/cases/type/time_test.rb new file mode 100644 index 0000000000..0cc4d33caa --- /dev/null +++ b/activemodel/test/cases/type/time_test.rb @@ -0,0 +1,21 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class TimeTest < ActiveModel::TestCase + def test_type_cast_time + type = Type::Time.new + assert_nil type.cast(nil) + assert_nil type.cast("") + assert_nil type.cast("ABC") + + time_string = ::Time.now.utc.strftime("%T") + assert_equal time_string, type.cast(time_string).strftime("%T") + + assert_equal ::Time.utc(2000, 1, 1, 16, 45, 54), type.cast("2015-06-13T19:45:54+03:00") + assert_equal ::Time.utc(1999, 12, 31, 21, 7, 8), type.cast("06:07:08+09:00") + end + end + end +end diff --git a/activemodel/test/cases/type/unsigned_integer_test.rb b/activemodel/test/cases/type/unsigned_integer_test.rb deleted file mode 100644 index 026cb08a06..0000000000 --- a/activemodel/test/cases/type/unsigned_integer_test.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "cases/helper" -require "active_model/type" - -module ActiveModel - module Type - class UnsignedIntegerTest < ActiveModel::TestCase - test "unsigned int max value is in range" do - assert_equal(4294967295, UnsignedInteger.new.serialize(4294967295)) - end - - test "minus value is out of range" do - assert_raises(ActiveModel::RangeError) do - UnsignedInteger.new.serialize(-1) - end - end - end - end -end diff --git a/activemodel/test/cases/type/value_test.rb b/activemodel/test/cases/type/value_test.rb new file mode 100644 index 0000000000..d8b3e7f164 --- /dev/null +++ b/activemodel/test/cases/type/value_test.rb @@ -0,0 +1,14 @@ +require "cases/helper" +require "active_model/type" + +module ActiveModel + module Type + class ValueTest < ActiveModel::TestCase + def test_type_equality + assert_equal Type::Value.new, Type::Value.new + assert_not_equal Type::Value.new, Type::Integer.new + assert_not_equal Type::Value.new(precision: 1), Type::Value.new(precision: 2) + end + end + end +end diff --git a/activemodel/test/cases/types_test.rb b/activemodel/test/cases/types_test.rb deleted file mode 100644 index 558c56f157..0000000000 --- a/activemodel/test/cases/types_test.rb +++ /dev/null @@ -1,125 +0,0 @@ -require "cases/helper" -require "active_model/type" -require "active_support/core_ext/numeric/time" - -module ActiveModel - class TypesTest < ActiveModel::TestCase - def test_type_cast_boolean - type = Type::Boolean.new - assert type.cast('').nil? - assert type.cast(nil).nil? - - assert type.cast(true) - assert type.cast(1) - assert type.cast('1') - assert type.cast('t') - assert type.cast('T') - assert type.cast('true') - assert type.cast('TRUE') - assert type.cast('on') - assert type.cast('ON') - assert type.cast(' ') - assert type.cast("\u3000\r\n") - assert type.cast("\u0000") - assert type.cast('SOMETHING RANDOM') - - # explicitly check for false vs nil - assert_equal false, type.cast(false) - assert_equal false, type.cast(0) - assert_equal false, type.cast('0') - assert_equal false, type.cast('f') - assert_equal false, type.cast('F') - assert_equal false, type.cast('false') - assert_equal false, type.cast('FALSE') - assert_equal false, type.cast('off') - assert_equal false, type.cast('OFF') - end - - def test_type_cast_float - type = Type::Float.new - assert_equal 1.0, type.cast("1") - end - - def test_changing_float - type = Type::Float.new - - assert type.changed?(5.0, 5.0, '5wibble') - assert_not type.changed?(5.0, 5.0, '5') - assert_not type.changed?(5.0, 5.0, '5.0') - assert_not type.changed?(nil, nil, nil) - end - - def test_type_cast_binary - type = Type::Binary.new - assert_equal nil, type.cast(nil) - assert_equal "1", type.cast("1") - assert_equal 1, type.cast(1) - end - - def test_type_cast_time - type = Type::Time.new - assert_equal nil, type.cast(nil) - assert_equal nil, type.cast('') - assert_equal nil, type.cast('ABC') - - time_string = Time.now.utc.strftime("%T") - assert_equal time_string, type.cast(time_string).strftime("%T") - - assert_equal ::Time.utc(2000, 1, 1, 16, 45, 54), type.cast('2015-06-13T19:45:54+03:00') - assert_equal ::Time.utc(1999, 12, 31, 21, 7, 8), type.cast('06:07:08+09:00') - end - - def test_type_cast_datetime_and_timestamp - type = Type::DateTime.new - assert_equal nil, type.cast(nil) - assert_equal nil, type.cast('') - assert_equal nil, type.cast(' ') - assert_equal nil, type.cast('ABC') - - datetime_string = Time.now.utc.strftime("%FT%T") - assert_equal datetime_string, type.cast(datetime_string).strftime("%FT%T") - end - - def test_type_cast_date - type = Type::Date.new - assert_equal nil, type.cast(nil) - assert_equal nil, type.cast('') - assert_equal nil, type.cast(' ') - assert_equal nil, type.cast('ABC') - - date_string = Time.now.utc.strftime("%F") - assert_equal date_string, type.cast(date_string).strftime("%F") - end - - def test_type_cast_duration_to_integer - type = Type::Integer.new - assert_equal 1800, type.cast(30.minutes) - assert_equal 7200, type.cast(2.hours) - end - - def test_string_to_time_with_timezone - ["UTC", "US/Eastern"].each do |zone| - with_timezone_config default: zone do - type = Type::DateTime.new - assert_equal Time.utc(2013, 9, 4, 0, 0, 0), type.cast("Wed, 04 Sep 2013 03:00:00 EAT") - end - end - end - - def test_type_equality - assert_equal Type::Value.new, Type::Value.new - assert_not_equal Type::Value.new, Type::Integer.new - assert_not_equal Type::Value.new(precision: 1), Type::Value.new(precision: 2) - end - - private - - def with_timezone_config(default:) - old_zone_default = ::Time.zone_default - ::Time.zone_default = ::Time.find_zone(default) - yield - ensure - ::Time.zone_default = old_zone_default - end - end -end diff --git a/activemodel/test/cases/validations/absence_validation_test.rb b/activemodel/test/cases/validations/absence_validation_test.rb index 9cbc77dfb5..833f694c5a 100644 --- a/activemodel/test/cases/validations/absence_validation_test.rb +++ b/activemodel/test/cases/validations/absence_validation_test.rb @@ -1,7 +1,7 @@ -require 'cases/helper' -require 'models/topic' -require 'models/person' -require 'models/custom_reader' +require "cases/helper" +require "models/topic" +require "models/person" +require "models/custom_reader" class AbsenceValidationTest < ActiveModel::TestCase teardown do @@ -19,7 +19,7 @@ class AbsenceValidationTest < ActiveModel::TestCase assert_equal ["must be blank"], t.errors[:title] assert_equal ["must be blank"], t.errors[:content] t.title = "" - t.content = "something" + t.content = "something" assert t.invalid? assert_equal ["must be blank"], t.errors[:content] assert_equal [], t.errors[:title] diff --git a/activemodel/test/cases/validations/acceptance_validation_test.rb b/activemodel/test/cases/validations/acceptance_validation_test.rb index d3995ad5af..fbd994e914 100644 --- a/activemodel/test/cases/validations/acceptance_validation_test.rb +++ b/activemodel/test/cases/validations/acceptance_validation_test.rb @@ -1,11 +1,10 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/reply' -require 'models/person' +require "models/topic" +require "models/reply" +require "models/person" class AcceptanceValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -20,7 +19,7 @@ class AcceptanceValidationTest < ActiveModel::TestCase def test_terms_of_service_agreement Topic.validates_acceptance_of(:terms_of_service) - t = Topic.new("title" => "We should be confirmed","terms_of_service" => "") + t = Topic.new("title" => "We should be confirmed", "terms_of_service" => "") assert t.invalid? assert_equal ["must be accepted"], t.errors[:terms_of_service] @@ -31,7 +30,7 @@ class AcceptanceValidationTest < ActiveModel::TestCase def test_eula Topic.validates_acceptance_of(:eula, message: "must be abided") - t = Topic.new("title" => "We should be confirmed","eula" => "") + t = Topic.new("title" => "We should be confirmed", "eula" => "") assert t.invalid? assert_equal ["must be abided"], t.errors[:eula] diff --git a/activemodel/test/cases/validations/callbacks_test.rb b/activemodel/test/cases/validations/callbacks_test.rb index 75eb18e795..83e8ac9522 100644 --- a/activemodel/test/cases/validations/callbacks_test.rb +++ b/activemodel/test/cases/validations/callbacks_test.rb @@ -1,4 +1,4 @@ -require 'cases/helper' +require "cases/helper" class Dog include ActiveModel::Validations @@ -15,37 +15,37 @@ class DogWithMethodCallbacks < Dog before_validation :set_before_validation_marker after_validation :set_after_validation_marker - def set_before_validation_marker; self.history << 'before_validation_marker'; end - def set_after_validation_marker; self.history << 'after_validation_marker' ; end + def set_before_validation_marker; history << "before_validation_marker"; end + def set_after_validation_marker; history << "after_validation_marker" ; end end class DogValidatorsAreProc < Dog - before_validation { self.history << 'before_validation_marker' } - after_validation { self.history << 'after_validation_marker' } + before_validation { history << "before_validation_marker" } + after_validation { history << "after_validation_marker" } end class DogWithTwoValidators < Dog - before_validation { self.history << 'before_validation_marker1' } - before_validation { self.history << 'before_validation_marker2' } + before_validation { history << "before_validation_marker1" } + before_validation { history << "before_validation_marker2" } end class DogDeprecatedBeforeValidatorReturningFalse < Dog before_validation { false } - before_validation { self.history << 'before_validation_marker2' } + before_validation { history << "before_validation_marker2" } end class DogBeforeValidatorThrowingAbort < Dog before_validation { throw :abort } - before_validation { self.history << 'before_validation_marker2' } + before_validation { history << "before_validation_marker2" } end class DogAfterValidatorReturningFalse < Dog after_validation { false } - after_validation { self.history << 'after_validation_marker' } + after_validation { history << "after_validation_marker" } end class DogWithMissingName < Dog - before_validation { self.history << 'before_validation_marker' } + before_validation { history << "before_validation_marker" } validates_presence_of :name end @@ -53,8 +53,8 @@ class DogValidatorWithOnCondition < Dog before_validation :set_before_validation_marker, on: :create after_validation :set_after_validation_marker, on: :create - def set_before_validation_marker; self.history << 'before_validation_marker'; end - def set_after_validation_marker; self.history << 'after_validation_marker' ; end + def set_before_validation_marker; history << "before_validation_marker"; end + def set_after_validation_marker; history << "after_validation_marker" ; end end class DogValidatorWithIfCondition < Dog @@ -64,16 +64,14 @@ class DogValidatorWithIfCondition < Dog after_validation :set_after_validation_marker1, if: -> { true } after_validation :set_after_validation_marker2, if: -> { false } - def set_before_validation_marker1; self.history << 'before_validation_marker1'; end - def set_before_validation_marker2; self.history << 'before_validation_marker2' ; end + def set_before_validation_marker1; history << "before_validation_marker1"; end + def set_before_validation_marker2; history << "before_validation_marker2" ; end - def set_after_validation_marker1; self.history << 'after_validation_marker1'; end - def set_after_validation_marker2; self.history << 'after_validation_marker2' ; end + def set_after_validation_marker1; history << "after_validation_marker1"; end + def set_after_validation_marker2; history << "after_validation_marker2" ; end end - class CallbacksWithMethodNamesShouldBeCalled < ActiveModel::TestCase - def test_if_condition_is_respected_for_before_validation d = DogValidatorWithIfCondition.new d.valid? @@ -101,19 +99,19 @@ class CallbacksWithMethodNamesShouldBeCalled < ActiveModel::TestCase def test_before_validation_and_after_validation_callbacks_should_be_called d = DogWithMethodCallbacks.new d.valid? - assert_equal ['before_validation_marker', 'after_validation_marker'], d.history + assert_equal ["before_validation_marker", "after_validation_marker"], d.history end def test_before_validation_and_after_validation_callbacks_should_be_called_with_proc d = DogValidatorsAreProc.new d.valid? - assert_equal ['before_validation_marker', 'after_validation_marker'], d.history + assert_equal ["before_validation_marker", "after_validation_marker"], d.history end def test_before_validation_and_after_validation_callbacks_should_be_called_in_declared_order d = DogWithTwoValidators.new d.valid? - assert_equal ['before_validation_marker1', 'before_validation_marker2'], d.history + assert_equal ["before_validation_marker1", "before_validation_marker2"], d.history end def test_further_callbacks_should_not_be_called_if_before_validation_throws_abort @@ -135,14 +133,13 @@ class CallbacksWithMethodNamesShouldBeCalled < ActiveModel::TestCase def test_further_callbacks_should_be_called_if_after_validation_returns_false d = DogAfterValidatorReturningFalse.new d.valid? - assert_equal ['after_validation_marker'], d.history + assert_equal ["after_validation_marker"], d.history end def test_validation_test_should_be_done d = DogWithMissingName.new output = d.valid? - assert_equal ['before_validation_marker'], d.history + assert_equal ["before_validation_marker"], d.history assert_equal false, output end - end diff --git a/activemodel/test/cases/validations/conditional_validation_test.rb b/activemodel/test/cases/validations/conditional_validation_test.rb index 296d3b4407..4881008017 100644 --- a/activemodel/test/cases/validations/conditional_validation_test.rb +++ b/activemodel/test/cases/validations/conditional_validation_test.rb @@ -1,9 +1,8 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' +require "models/topic" class ConditionalValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -98,7 +97,7 @@ class ConditionalValidationTest < ActiveModel::TestCase def test_if_validation_using_block_false # When the block returns false Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", - if: Proc.new { |r| r.title != "uhohuhoh"}) + if: Proc.new { |r| r.title != "uhohuhoh" }) t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.valid? assert_empty t.errors[:title] @@ -107,7 +106,7 @@ class ConditionalValidationTest < ActiveModel::TestCase def test_unless_validation_using_block_false # When the block returns false Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", - unless: Proc.new { |r| r.title != "uhohuhoh"} ) + unless: Proc.new { |r| r.title != "uhohuhoh" }) t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? diff --git a/activemodel/test/cases/validations/confirmation_validation_test.rb b/activemodel/test/cases/validations/confirmation_validation_test.rb index c56bf1c0ad..7ddf3ad273 100644 --- a/activemodel/test/cases/validations/confirmation_validation_test.rb +++ b/activemodel/test/cases/validations/confirmation_validation_test.rb @@ -1,10 +1,9 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/person' +require "models/topic" +require "models/person" class ConfirmationValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -29,7 +28,7 @@ class ConfirmationValidationTest < ActiveModel::TestCase def test_title_confirmation Topic.validates_confirmation_of(:title) - t = Topic.new("title" => "We should be confirmed","title_confirmation" => "") + t = Topic.new("title" => "We should be confirmed", "title_confirmation" => "") assert t.invalid? t.title_confirmation = "We should be confirmed" @@ -56,14 +55,13 @@ class ConfirmationValidationTest < ActiveModel::TestCase @old_load_path, @old_backend = I18n.load_path.dup, I18n.backend I18n.load_path.clear I18n.backend = I18n::Backend::Simple.new - I18n.backend.store_translations('en', { + I18n.backend.store_translations("en", errors: { messages: { confirmation: "doesn't match %{attribute}" } }, - activemodel: { attributes: { topic: { title: 'Test Title'} } } - }) + activemodel: { attributes: { topic: { title: "Test Title" } } }) Topic.validates_confirmation_of(:title) - t = Topic.new("title" => "We should be confirmed","title_confirmation" => "") + t = Topic.new("title" => "We should be confirmed", "title_confirmation" => "") assert t.invalid? assert_equal ["doesn't match Test Title"], t.errors[:title_confirmation] ensure diff --git a/activemodel/test/cases/validations/exclusion_validation_test.rb b/activemodel/test/cases/validations/exclusion_validation_test.rb index 005bc15df5..06ae4fbecd 100644 --- a/activemodel/test/cases/validations/exclusion_validation_test.rb +++ b/activemodel/test/cases/validations/exclusion_validation_test.rb @@ -1,11 +1,10 @@ -require 'cases/helper' -require 'active_support/core_ext/numeric/time' +require "cases/helper" +require "active_support/core_ext/numeric/time" -require 'models/topic' -require 'models/person' +require "models/topic" +require "models/person" class ExclusionValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -68,8 +67,8 @@ class ExclusionValidationTest < ActiveModel::TestCase def test_validates_exclusion_of_with_range Topic.validates_exclusion_of :content, in: ("a".."g") - assert Topic.new(content: 'g').invalid? - assert Topic.new(content: 'h').valid? + assert Topic.new(content: "g").invalid? + assert Topic.new(content: "h").valid? end def test_validates_exclusion_of_with_time_range diff --git a/activemodel/test/cases/validations/format_validation_test.rb b/activemodel/test/cases/validations/format_validation_test.rb index ea4c2ee7df..d7e6bf3707 100644 --- a/activemodel/test/cases/validations/format_validation_test.rb +++ b/activemodel/test/cases/validations/format_validation_test.rb @@ -1,10 +1,9 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/person' +require "models/topic" +require "models/person" class PresenceValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -63,7 +62,7 @@ class PresenceValidationTest < ActiveModel::TestCase def test_validate_format_with_formatted_message Topic.validates_format_of(:title, with: /\AValid Title\z/, message: "can't be %{value}") - t = Topic.new(title: 'Invalid title') + t = Topic.new(title: "Invalid title") assert t.invalid? assert_equal ["can't be Invalid title"], t.errors[:title] end diff --git a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb index da63df9152..f049ee26e8 100644 --- a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -require 'models/person' +require "models/person" class I18nGenerateMessageValidationTest < ActiveModel::TestCase def setup @@ -10,29 +10,29 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase # validates_inclusion_of: generate_message(attr_name, :inclusion, message: custom_message, value: value) def test_generate_message_inclusion_with_default_message - assert_equal 'is not included in the list', @person.errors.generate_message(:title, :inclusion, value: 'title') + assert_equal "is not included in the list", @person.errors.generate_message(:title, :inclusion, value: "title") end def test_generate_message_inclusion_with_custom_message - assert_equal 'custom message title', @person.errors.generate_message(:title, :inclusion, message: 'custom message %{value}', value: 'title') + assert_equal "custom message title", @person.errors.generate_message(:title, :inclusion, message: "custom message %{value}", value: "title") end # validates_exclusion_of: generate_message(attr_name, :exclusion, message: custom_message, value: value) def test_generate_message_exclusion_with_default_message - assert_equal 'is reserved', @person.errors.generate_message(:title, :exclusion, value: 'title') + assert_equal "is reserved", @person.errors.generate_message(:title, :exclusion, value: "title") end def test_generate_message_exclusion_with_custom_message - assert_equal 'custom message title', @person.errors.generate_message(:title, :exclusion, message: 'custom message %{value}', value: 'title') + assert_equal "custom message title", @person.errors.generate_message(:title, :exclusion, message: "custom message %{value}", value: "title") end # validates_format_of: generate_message(attr_name, :invalid, message: custom_message, value: value) def test_generate_message_invalid_with_default_message - assert_equal 'is invalid', @person.errors.generate_message(:title, :invalid, value: 'title') + assert_equal "is invalid", @person.errors.generate_message(:title, :invalid, value: "title") end def test_generate_message_invalid_with_custom_message - assert_equal 'custom message title', @person.errors.generate_message(:title, :invalid, message: 'custom message %{value}', value: 'title') + assert_equal "custom message title", @person.errors.generate_message(:title, :invalid, message: "custom message %{value}", value: "title") end # validates_confirmation_of: generate_message(attr_name, :confirmation, message: custom_message) @@ -41,7 +41,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_confirmation_with_custom_message - assert_equal 'custom message', @person.errors.generate_message(:title, :confirmation, message: 'custom message') + assert_equal "custom message", @person.errors.generate_message(:title, :confirmation, message: "custom message") end # validates_acceptance_of: generate_message(attr_name, :accepted, message: custom_message) @@ -50,7 +50,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_accepted_with_custom_message - assert_equal 'custom message', @person.errors.generate_message(:title, :accepted, message: 'custom message') + assert_equal "custom message", @person.errors.generate_message(:title, :accepted, message: "custom message") end # add_on_empty: generate_message(attr, :empty, message: custom_message) @@ -59,7 +59,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_empty_with_custom_message - assert_equal 'custom message', @person.errors.generate_message(:title, :empty, message: 'custom message') + assert_equal "custom message", @person.errors.generate_message(:title, :empty, message: "custom message") end # validates_presence_of: generate_message(attr, :blank, message: custom_message) @@ -68,7 +68,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_blank_with_custom_message - assert_equal 'custom message', @person.errors.generate_message(:title, :blank, message: 'custom message') + assert_equal "custom message", @person.errors.generate_message(:title, :blank, message: "custom message") end # validates_length_of: generate_message(attr, :too_long, message: custom_message, count: option_value.end) @@ -81,7 +81,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_too_long_with_custom_message - assert_equal 'custom message 10', @person.errors.generate_message(:title, :too_long, message: 'custom message %{count}', count: 10) + assert_equal "custom message 10", @person.errors.generate_message(:title, :too_long, message: "custom message %{count}", count: 10) end # validates_length_of: generate_message(attr, :too_short, default: custom_message, count: option_value.begin) @@ -94,7 +94,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_too_short_with_custom_message - assert_equal 'custom message 10', @person.errors.generate_message(:title, :too_short, message: 'custom message %{count}', count: 10) + assert_equal "custom message 10", @person.errors.generate_message(:title, :too_short, message: "custom message %{count}", count: 10) end # validates_length_of: generate_message(attr, :wrong_length, message: custom_message, count: option_value) @@ -107,44 +107,44 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase end def test_generate_message_wrong_length_with_custom_message - assert_equal 'custom message 10', @person.errors.generate_message(:title, :wrong_length, message: 'custom message %{count}', count: 10) + assert_equal "custom message 10", @person.errors.generate_message(:title, :wrong_length, message: "custom message %{count}", count: 10) end # validates_numericality_of: generate_message(attr_name, :not_a_number, value: raw_value, message: custom_message) def test_generate_message_not_a_number_with_default_message - assert_equal "is not a number", @person.errors.generate_message(:title, :not_a_number, value: 'title') + assert_equal "is not a number", @person.errors.generate_message(:title, :not_a_number, value: "title") end def test_generate_message_not_a_number_with_custom_message - assert_equal 'custom message title', @person.errors.generate_message(:title, :not_a_number, message: 'custom message %{value}', value: 'title') + assert_equal "custom message title", @person.errors.generate_message(:title, :not_a_number, message: "custom message %{value}", value: "title") end # validates_numericality_of: generate_message(attr_name, option, value: raw_value, default: custom_message) def test_generate_message_greater_than_with_default_message - assert_equal "must be greater than 10", @person.errors.generate_message(:title, :greater_than, value: 'title', count: 10) + assert_equal "must be greater than 10", @person.errors.generate_message(:title, :greater_than, value: "title", count: 10) end def test_generate_message_greater_than_or_equal_to_with_default_message - assert_equal "must be greater than or equal to 10", @person.errors.generate_message(:title, :greater_than_or_equal_to, value: 'title', count: 10) + assert_equal "must be greater than or equal to 10", @person.errors.generate_message(:title, :greater_than_or_equal_to, value: "title", count: 10) end def test_generate_message_equal_to_with_default_message - assert_equal "must be equal to 10", @person.errors.generate_message(:title, :equal_to, value: 'title', count: 10) + assert_equal "must be equal to 10", @person.errors.generate_message(:title, :equal_to, value: "title", count: 10) end def test_generate_message_less_than_with_default_message - assert_equal "must be less than 10", @person.errors.generate_message(:title, :less_than, value: 'title', count: 10) + assert_equal "must be less than 10", @person.errors.generate_message(:title, :less_than, value: "title", count: 10) end def test_generate_message_less_than_or_equal_to_with_default_message - assert_equal "must be less than or equal to 10", @person.errors.generate_message(:title, :less_than_or_equal_to, value: 'title', count: 10) + assert_equal "must be less than or equal to 10", @person.errors.generate_message(:title, :less_than_or_equal_to, value: "title", count: 10) end def test_generate_message_odd_with_default_message - assert_equal "must be odd", @person.errors.generate_message(:title, :odd, value: 'title', count: 10) + assert_equal "must be odd", @person.errors.generate_message(:title, :odd, value: "title", count: 10) end def test_generate_message_even_with_default_message - assert_equal "must be even", @person.errors.generate_message(:title, :even, value: 'title', count: 10) + assert_equal "must be even", @person.errors.generate_message(:title, :even, value: "title", count: 10) end end diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb index 09d7226b5a..f28cfc0ef5 100644 --- a/activemodel/test/cases/validations/i18n_validation_test.rb +++ b/activemodel/test/cases/validations/i18n_validation_test.rb @@ -1,8 +1,7 @@ require "cases/helper" -require 'models/person' +require "models/person" class I18nValidationTest < ActiveModel::TestCase - def setup Person.clear_validators! @person = Person.new @@ -10,7 +9,7 @@ class I18nValidationTest < ActiveModel::TestCase @old_load_path, @old_backend = I18n.load_path.dup, I18n.backend I18n.load_path.clear I18n.backend = I18n::Backend::Simple.new - I18n.backend.store_translations('en', errors: { messages: { custom: nil } }) + I18n.backend.store_translations("en", errors: { messages: { custom: nil } }) end def teardown @@ -21,23 +20,23 @@ class I18nValidationTest < ActiveModel::TestCase end def test_full_message_encoding - I18n.backend.store_translations('en', errors: { - messages: { too_short: '猫舌' } }) + I18n.backend.store_translations("en", errors: { + messages: { too_short: "猫舌" } }) Person.validates_length_of :title, within: 3..5 @person.valid? - assert_equal ['Title 猫舌'], @person.errors.full_messages + assert_equal ["Title 猫舌"], @person.errors.full_messages end def test_errors_full_messages_translates_human_attribute_name_for_model_attributes - @person.errors.add(:name, 'not found') - assert_called_with(Person, :human_attribute_name, [:name, default: 'Name'], returns: "Person's name") do + @person.errors.add(:name, "not found") + assert_called_with(Person, :human_attribute_name, [:name, default: "Name"], returns: "Person's name") do assert_equal ["Person's name not found"], @person.errors.full_messages end end def test_errors_full_messages_uses_format - I18n.backend.store_translations('en', errors: { format: "Field %{attribute} %{message}" }) - @person.errors.add('name', 'empty') + I18n.backend.store_translations("en", errors: { format: "Field %{attribute} %{message}" }) + @person.errors.add("name", "empty") assert_equal ["Field Name empty"], @person.errors.full_messages end @@ -47,19 +46,19 @@ class I18nValidationTest < ActiveModel::TestCase # are used to generate tests to keep things DRY # COMMON_CASES = [ - # [ case, validation_options, generate_message_options] + # [ case, validation_options, generate_message_options] [ "given no options", {}, {}], [ "given custom message", { message: "custom" }, { message: "custom" }], - [ "given if condition", { if: lambda { true }}, {}], - [ "given unless condition", { unless: lambda { false }}, {}], + [ "given if condition", { if: lambda { true } }, {}], + [ "given unless condition", { unless: lambda { false } }, {}], [ "given option that is not reserved", { format: "jpg" }, { format: "jpg" }] ] COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_confirmation_of on generated message #{name}" do Person.validates_confirmation_of :title, validation_options - @person.title_confirmation = 'foo' - call = [:title_confirmation, :confirmation, generate_message_options.merge(attribute: 'Title')] + @person.title_confirmation = "foo" + call = [:title_confirmation, :confirmation, generate_message_options.merge(attribute: "Title")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -99,7 +98,7 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_length_of for :too_long generated message #{name}" do Person.validates_length_of :title, validation_options.merge(within: 3..5) - @person.title = 'this title is too long' + @person.title = "this title is too long" call = [:title, :too_long, generate_message_options.merge(count: 5)] assert_called_with(@person.errors, :generate_message, call) do @person.valid? @@ -120,8 +119,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_format_of on generated message #{name}" do Person.validates_format_of :title, validation_options.merge(with: /\A[1-9][0-9]*\z/) - @person.title = '72x' - call = [:title, :invalid, generate_message_options.merge(value: '72x')] + @person.title = "72x" + call = [:title, :invalid, generate_message_options.merge(value: "72x")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -131,8 +130,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_inclusion_of on generated message #{name}" do Person.validates_inclusion_of :title, validation_options.merge(in: %w(a b c)) - @person.title = 'z' - call = [:title, :inclusion, generate_message_options.merge(value: 'z')] + @person.title = "z" + call = [:title, :inclusion, generate_message_options.merge(value: "z")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -142,8 +141,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_inclusion_of using :within on generated message #{name}" do Person.validates_inclusion_of :title, validation_options.merge(within: %w(a b c)) - @person.title = 'z' - call = [:title, :inclusion, generate_message_options.merge(value: 'z')] + @person.title = "z" + call = [:title, :inclusion, generate_message_options.merge(value: "z")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -153,8 +152,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_exclusion_of generated message #{name}" do Person.validates_exclusion_of :title, validation_options.merge(in: %w(a b c)) - @person.title = 'a' - call = [:title, :exclusion, generate_message_options.merge(value: 'a')] + @person.title = "a" + call = [:title, :exclusion, generate_message_options.merge(value: "a")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -164,8 +163,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_exclusion_of using :within generated message #{name}" do Person.validates_exclusion_of :title, validation_options.merge(within: %w(a b c)) - @person.title = 'a' - call = [:title, :exclusion, generate_message_options.merge(value: 'a')] + @person.title = "a" + call = [:title, :exclusion, generate_message_options.merge(value: "a")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -175,8 +174,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_numericality_of generated message #{name}" do Person.validates_numericality_of :title, validation_options - @person.title = 'a' - call = [:title, :not_a_number, generate_message_options.merge(value: 'a')] + @person.title = "a" + call = [:title, :not_a_number, generate_message_options.merge(value: "a")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -186,8 +185,8 @@ class I18nValidationTest < ActiveModel::TestCase COMMON_CASES.each do |name, validation_options, generate_message_options| test "validates_numericality_of for :only_integer on generated message #{name}" do Person.validates_numericality_of :title, validation_options.merge(only_integer: true) - @person.title = '0.0' - call = [:title, :not_an_integer, generate_message_options.merge(value: '0.0')] + @person.title = "0.0" + call = [:title, :not_an_integer, generate_message_options.merge(value: "0.0")] assert_called_with(@person.errors, :generate_message, call) do @person.valid? end @@ -225,35 +224,35 @@ class I18nValidationTest < ActiveModel::TestCase end test "#{validation} finds custom model key translation when #{error_type}" do - I18n.backend.store_translations 'en', activemodel: { errors: { models: { person: { attributes: { attribute => { error_type => 'custom message' } } } } } } - I18n.backend.store_translations 'en', errors: { messages: { error_type => 'global message'}} + I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { attributes: { attribute => { error_type => "custom message" } } } } } } + I18n.backend.store_translations "en", errors: { messages: { error_type => "global message" } } yield(@person, {}) @person.valid? - assert_equal ['custom message'], @person.errors[attribute] + assert_equal ["custom message"], @person.errors[attribute] end test "#{validation} finds custom model key translation with interpolation when #{error_type}" do - I18n.backend.store_translations 'en', activemodel: { errors: { models: { person: { attributes: { attribute => { error_type => 'custom message with %{extra}' } } } } } } - I18n.backend.store_translations 'en', errors: { messages: {error_type => 'global message'} } + I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { attributes: { attribute => { error_type => "custom message with %{extra}" } } } } } } + I18n.backend.store_translations "en", errors: { messages: { error_type => "global message" } } yield(@person, { extra: "extra information" }) @person.valid? - assert_equal ['custom message with extra information'], @person.errors[attribute] + assert_equal ["custom message with extra information"], @person.errors[attribute] end test "#{validation} finds global default key translation when #{error_type}" do - I18n.backend.store_translations 'en', errors: { messages: {error_type => 'global message'} } + I18n.backend.store_translations "en", errors: { messages: { error_type => "global message" } } yield(@person, {}) @person.valid? - assert_equal ['global message'], @person.errors[attribute] + assert_equal ["global message"], @person.errors[attribute] end end set_expectations_for_validation "validates_confirmation_of", :confirmation do |person, options_to_merge| Person.validates_confirmation_of :title, options_to_merge - person.title_confirmation = 'foo' + person.title_confirmation = "foo" end set_expectations_for_validation "validates_acceptance_of", :accepted do |person, options_to_merge| @@ -287,17 +286,17 @@ class I18nValidationTest < ActiveModel::TestCase set_expectations_for_validation "validates_exclusion_of", :exclusion do |person, options_to_merge| Person.validates_exclusion_of :title, options_to_merge.merge(in: %w(a b c)) - person.title = 'a' + person.title = "a" end set_expectations_for_validation "validates_numericality_of", :not_a_number do |person, options_to_merge| Person.validates_numericality_of :title, options_to_merge - person.title = 'a' + person.title = "a" end set_expectations_for_validation "validates_numericality_of", :not_an_integer do |person, options_to_merge| Person.validates_numericality_of :title, options_to_merge.merge(only_integer: true) - person.title = '1.0' + person.title = "1.0" end set_expectations_for_validation "validates_numericality_of", :odd do |person, options_to_merge| @@ -311,7 +310,7 @@ class I18nValidationTest < ActiveModel::TestCase end def test_validations_with_message_symbol_must_translate - I18n.backend.store_translations 'en', errors: { messages: { custom_error: "I am a custom error" } } + I18n.backend.store_translations "en", errors: { messages: { custom_error: "I am a custom error" } } Person.validates_presence_of :title, message: :custom_error @person.title = nil @person.valid? @@ -319,7 +318,7 @@ class I18nValidationTest < ActiveModel::TestCase end def test_validates_with_message_symbol_must_translate_per_attribute - I18n.backend.store_translations 'en', activemodel: { errors: { models: { person: { attributes: { title: { custom_error: "I am a custom error" } } } } } } + I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { attributes: { title: { custom_error: "I am a custom error" } } } } } } Person.validates_presence_of :title, message: :custom_error @person.title = nil @person.valid? @@ -327,7 +326,7 @@ class I18nValidationTest < ActiveModel::TestCase end def test_validates_with_message_symbol_must_translate_per_model - I18n.backend.store_translations 'en', activemodel: { errors: { models: { person: { custom_error: "I am a custom error" } } } } + I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { custom_error: "I am a custom error" } } } } Person.validates_presence_of :title, message: :custom_error @person.title = nil @person.valid? diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb index 9bd44175a6..5aa43ea4a9 100644 --- a/activemodel/test/cases/validations/inclusion_validation_test.rb +++ b/activemodel/test/cases/validations/inclusion_validation_test.rb @@ -1,17 +1,16 @@ -require 'cases/helper' -require 'active_support/all' +require "cases/helper" +require "active_support/all" -require 'models/topic' -require 'models/person' +require "models/topic" +require "models/person" class InclusionValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end def test_validates_inclusion_of_range - Topic.validates_inclusion_of(:title, in: 'aaa'..'bbb') + Topic.validates_inclusion_of(:title, in: "aaa".."bbb") assert Topic.new("title" => "bbc", "content" => "abc").invalid? assert Topic.new("title" => "aa", "content" => "abc").invalid? assert Topic.new("title" => "aaab", "content" => "abc").invalid? @@ -24,35 +23,35 @@ class InclusionValidationTest < ActiveModel::TestCase range_begin = 1.year.ago range_end = Time.now Topic.validates_inclusion_of(:created_at, in: range_begin..range_end) - assert Topic.new(title: 'aaa', created_at: 2.years.ago).invalid? - assert Topic.new(title: 'aaa', created_at: 3.months.ago).valid? - assert Topic.new(title: 'aaa', created_at: 37.weeks.from_now).invalid? - assert Topic.new(title: 'aaa', created_at: range_begin).valid? - assert Topic.new(title: 'aaa', created_at: range_end).valid? + assert Topic.new(title: "aaa", created_at: 2.years.ago).invalid? + assert Topic.new(title: "aaa", created_at: 3.months.ago).valid? + assert Topic.new(title: "aaa", created_at: 37.weeks.from_now).invalid? + assert Topic.new(title: "aaa", created_at: range_begin).valid? + assert Topic.new(title: "aaa", created_at: range_end).valid? end def test_validates_inclusion_of_date_range range_begin = 1.year.until(Date.today) range_end = Date.today Topic.validates_inclusion_of(:created_at, in: range_begin..range_end) - assert Topic.new(title: 'aaa', created_at: 2.years.until(Date.today)).invalid? - assert Topic.new(title: 'aaa', created_at: 3.months.until(Date.today)).valid? - assert Topic.new(title: 'aaa', created_at: 37.weeks.since(Date.today)).invalid? - assert Topic.new(title: 'aaa', created_at: 1.year.until(Date.today)).valid? - assert Topic.new(title: 'aaa', created_at: Date.today).valid? - assert Topic.new(title: 'aaa', created_at: range_begin).valid? - assert Topic.new(title: 'aaa', created_at: range_end).valid? + assert Topic.new(title: "aaa", created_at: 2.years.until(Date.today)).invalid? + assert Topic.new(title: "aaa", created_at: 3.months.until(Date.today)).valid? + assert Topic.new(title: "aaa", created_at: 37.weeks.since(Date.today)).invalid? + assert Topic.new(title: "aaa", created_at: 1.year.until(Date.today)).valid? + assert Topic.new(title: "aaa", created_at: Date.today).valid? + assert Topic.new(title: "aaa", created_at: range_begin).valid? + assert Topic.new(title: "aaa", created_at: range_end).valid? end def test_validates_inclusion_of_date_time_range range_begin = 1.year.until(DateTime.current) range_end = DateTime.current Topic.validates_inclusion_of(:created_at, in: range_begin..range_end) - assert Topic.new(title: 'aaa', created_at: 2.years.until(DateTime.current)).invalid? - assert Topic.new(title: 'aaa', created_at: 3.months.until(DateTime.current)).valid? - assert Topic.new(title: 'aaa', created_at: 37.weeks.since(DateTime.current)).invalid? - assert Topic.new(title: 'aaa', created_at: range_begin).valid? - assert Topic.new(title: 'aaa', created_at: range_end).valid? + assert Topic.new(title: "aaa", created_at: 2.years.until(DateTime.current)).invalid? + assert Topic.new(title: "aaa", created_at: 3.months.until(DateTime.current)).valid? + assert Topic.new(title: "aaa", created_at: 37.weeks.since(DateTime.current)).invalid? + assert Topic.new(title: "aaa", created_at: range_begin).valid? + assert Topic.new(title: "aaa", created_at: range_end).valid? end def test_validates_inclusion_of @@ -122,7 +121,7 @@ class InclusionValidationTest < ActiveModel::TestCase end def test_validates_inclusion_of_with_lambda - Topic.validates_inclusion_of :title, in: lambda{ |topic| topic.author_name == "sikachu" ? %w( monkey elephant ) : %w( abe wasabi ) } + Topic.validates_inclusion_of :title, in: lambda { |topic| topic.author_name == "sikachu" ? %w( monkey elephant ) : %w( abe wasabi ) } t = Topic.new t.title = "wasabi" diff --git a/activemodel/test/cases/validations/length_validation_test.rb b/activemodel/test/cases/validations/length_validation_test.rb index 11dce1df20..95ee87b401 100644 --- a/activemodel/test/cases/validations/length_validation_test.rb +++ b/activemodel/test/cases/validations/length_validation_test.rb @@ -1,7 +1,7 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/person' +require "models/topic" +require "models/person" class LengthValidationTest < ActiveModel::TestCase def teardown @@ -9,7 +9,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_with_allow_nil - Topic.validates_length_of( :title, is: 5, allow_nil: true ) + Topic.validates_length_of(:title, is: 5, allow_nil: true) assert Topic.new("title" => "ab").invalid? assert Topic.new("title" => "").invalid? @@ -18,7 +18,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_with_allow_blank - Topic.validates_length_of( :title, is: 5, allow_blank: true ) + Topic.validates_length_of(:title, is: 5, allow_blank: true) assert Topic.new("title" => "ab").invalid? assert Topic.new("title" => "").valid? @@ -104,7 +104,7 @@ class LengthValidationTest < ActiveModel::TestCase assert_equal ["is too short (minimum is 3 characters)"], t.errors[:content] t.title = "abe" - t.content = "mad" + t.content = "mad" assert t.valid? end @@ -125,7 +125,7 @@ class LengthValidationTest < ActiveModel::TestCase def test_optionally_validates_length_of_using_within Topic.validates_length_of :title, :content, within: 3..5, allow_nil: true - t = Topic.new('title' => 'abc', 'content' => 'abcd') + t = Topic.new("title" => "abc", "content" => "abcd") assert t.valid? t.title = nil @@ -161,8 +161,8 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_using_bignum - bigmin = 2 ** 30 - bigmax = 2 ** 32 + bigmin = 2**30 + bigmax = 2**32 bigrange = bigmin...bigmax assert_nothing_raised do Topic.validates_length_of :title, is: bigmin + 5 @@ -183,7 +183,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_custom_errors_for_minimum_with_message - Topic.validates_length_of( :title, minimum: 5, message: "boo %{count}" ) + Topic.validates_length_of(:title, minimum: 5, message: "boo %{count}") t = Topic.new("title" => "uhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -191,7 +191,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_custom_errors_for_minimum_with_too_short - Topic.validates_length_of( :title, minimum: 5, too_short: "hoo %{count}" ) + Topic.validates_length_of(:title, minimum: 5, too_short: "hoo %{count}") t = Topic.new("title" => "uhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -199,7 +199,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_custom_errors_for_maximum_with_message - Topic.validates_length_of( :title, maximum: 5, message: "boo %{count}" ) + Topic.validates_length_of(:title, maximum: 5, message: "boo %{count}") t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -220,7 +220,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_custom_errors_for_maximum_with_too_long - Topic.validates_length_of( :title, maximum: 5, too_long: "hoo %{count}" ) + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}") t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -228,21 +228,21 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_custom_errors_for_both_too_short_and_too_long - Topic.validates_length_of :title, minimum: 3, maximum: 5, too_short: 'too short', too_long: 'too long' + Topic.validates_length_of :title, minimum: 3, maximum: 5, too_short: "too short", too_long: "too long" - t = Topic.new(title: 'a') + t = Topic.new(title: "a") assert t.invalid? assert t.errors[:title].any? - assert_equal ['too short'], t.errors['title'] + assert_equal ["too short"], t.errors["title"] - t = Topic.new(title: 'aaaaaa') + t = Topic.new(title: "aaaaaa") assert t.invalid? assert t.errors[:title].any? - assert_equal ['too long'], t.errors['title'] + assert_equal ["too long"], t.errors["title"] end def test_validates_length_of_custom_errors_for_is_with_message - Topic.validates_length_of( :title, is: 5, message: "boo %{count}" ) + Topic.validates_length_of(:title, is: 5, message: "boo %{count}") t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -250,7 +250,7 @@ class LengthValidationTest < ActiveModel::TestCase end def test_validates_length_of_custom_errors_for_is_with_wrong_length - Topic.validates_length_of( :title, is: 5, wrong_length: "hoo %{count}" ) + Topic.validates_length_of(:title, is: 5, wrong_length: "hoo %{count}") t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -289,7 +289,7 @@ class LengthValidationTest < ActiveModel::TestCase assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title] assert_equal ["is too long (maximum is 5 characters)"], t.errors[:content] t.title = "一二三" - t.content = "12三" + t.content = "12三" assert t.valid? end @@ -318,43 +318,6 @@ class LengthValidationTest < ActiveModel::TestCase assert_equal ["is the wrong length (should be 5 characters)"], t.errors["title"] end - def test_validates_length_of_with_block - assert_deprecated do - Topic.validates_length_of( - :content, - minimum: 5, - too_short: "Your essay must be at least %{count} words.", - tokenizer: lambda {|str| str.scan(/\w+/) }, - ) - end - t = Topic.new(content: "this content should be long enough") - assert t.valid? - - t.content = "not long enough" - assert t.invalid? - assert t.errors[:content].any? - assert_equal ["Your essay must be at least 5 words."], t.errors[:content] - end - - - def test_validates_length_of_with_symbol - assert_deprecated do - Topic.validates_length_of( - :content, - minimum: 5, - too_short: "Your essay must be at least %{count} words.", - tokenizer: :my_word_tokenizer, - ) - end - t = Topic.new(content: "this content should be long enough") - assert t.valid? - - t.content = "not long enough" - assert t.invalid? - assert t.errors[:content].any? - assert_equal ["Your essay must be at least 5 words."], t.errors[:content] - end - def test_validates_length_of_for_integer Topic.validates_length_of(:approved, is: 4) @@ -440,7 +403,7 @@ class LengthValidationTest < ActiveModel::TestCase def test_validates_with_diff_in_option Topic.validates_length_of(:title, is: 5) - Topic.validates_length_of(:title, is: 5, if: Proc.new { false } ) + Topic.validates_length_of(:title, is: 5, if: Proc.new { false }) assert Topic.new("title" => "david").valid? assert Topic.new("title" => "david2").invalid? diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb index 74a048537d..a1be2de578 100644 --- a/activemodel/test/cases/validations/numericality_validation_test.rb +++ b/activemodel/test/cases/validations/numericality_validation_test.rb @@ -1,13 +1,12 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/person' +require "models/topic" +require "models/person" -require 'bigdecimal' -require 'active_support/core_ext/big_decimal' +require "bigdecimal" +require "active_support/core_ext/big_decimal" class NumericalityValidationTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -21,7 +20,7 @@ class NumericalityValidationTest < ActiveModel::TestCase INTEGERS = [0, 10, -10] + INTEGER_STRINGS BIGDECIMAL = BIGDECIMAL_STRINGS.collect! { |bd| BigDecimal.new(bd) } JUNK = ["not a number", "42 not a number", "0xdeadbeef", "0xinvalidhex", "0Xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"] - INFINITY = [1.0/0.0] + INFINITY = [1.0 / 0.0] def test_default_validates_numericality_of Topic.validates_numericality_of :approved @@ -36,6 +35,13 @@ class NumericalityValidationTest < ActiveModel::TestCase valid!(NIL + FLOATS + INTEGERS + BIGDECIMAL + INFINITY) end + def test_validates_numericality_of_with_blank_allowed + Topic.validates_numericality_of :approved, allow_blank: true + + invalid!(JUNK) + valid!(NIL + BLANK + FLOATS + INTEGERS + BIGDECIMAL + INFINITY) + end + def test_validates_numericality_of_with_integer_only Topic.validates_numericality_of :approved, only_integer: true @@ -68,119 +74,119 @@ class NumericalityValidationTest < ActiveModel::TestCase def test_validates_numericality_with_greater_than Topic.validates_numericality_of :approved, greater_than: 10 - invalid!([-10, 10], 'must be greater than 10') + invalid!([-10, 10], "must be greater than 10") valid!([11]) end def test_validates_numericality_with_greater_than_using_differing_numeric_types - Topic.validates_numericality_of :approved, greater_than: BigDecimal.new('97.18') + Topic.validates_numericality_of :approved, greater_than: BigDecimal.new("97.18") - invalid!([-97.18, BigDecimal.new('97.18'), BigDecimal('-97.18')], 'must be greater than 97.18') - valid!([97.18, 98, BigDecimal.new('98')]) # Notice the 97.18 as a float is greater than 97.18 as a BigDecimal due to floating point precision + invalid!([-97.18, BigDecimal.new("97.18"), BigDecimal("-97.18")], "must be greater than 97.18") + valid!([97.19, 98, BigDecimal.new("98"), BigDecimal.new("97.19")]) end def test_validates_numericality_with_greater_than_using_string_value Topic.validates_numericality_of :approved, greater_than: 10 - invalid!(['-10', '9', '9.9', '10'], 'must be greater than 10') - valid!(['10.1', '11']) + invalid!(["-10", "9", "9.9", "10"], "must be greater than 10") + valid!(["10.1", "11"]) end def test_validates_numericality_with_greater_than_or_equal Topic.validates_numericality_of :approved, greater_than_or_equal_to: 10 - invalid!([-9, 9], 'must be greater than or equal to 10') + invalid!([-9, 9], "must be greater than or equal to 10") valid!([10]) end def test_validates_numericality_with_greater_than_or_equal_using_differing_numeric_types - Topic.validates_numericality_of :approved, greater_than_or_equal_to: BigDecimal.new('97.18') + Topic.validates_numericality_of :approved, greater_than_or_equal_to: BigDecimal.new("97.18") - invalid!([-97.18, 97.17, 97, BigDecimal.new('97.17'), BigDecimal.new('-97.18')], 'must be greater than or equal to 97.18') - valid!([97.18, 98, BigDecimal.new('97.19')]) + invalid!([-97.18, 97.17, 97, BigDecimal.new("97.17"), BigDecimal.new("-97.18")], "must be greater than or equal to 97.18") + valid!([97.18, 98, BigDecimal.new("97.19")]) end def test_validates_numericality_with_greater_than_or_equal_using_string_value Topic.validates_numericality_of :approved, greater_than_or_equal_to: 10 - invalid!(['-10', '9', '9.9'], 'must be greater than or equal to 10') - valid!(['10', '10.1', '11']) + invalid!(["-10", "9", "9.9"], "must be greater than or equal to 10") + valid!(["10", "10.1", "11"]) end def test_validates_numericality_with_equal_to Topic.validates_numericality_of :approved, equal_to: 10 - invalid!([-10, 11] + INFINITY, 'must be equal to 10') + invalid!([-10, 11] + INFINITY, "must be equal to 10") valid!([10]) end def test_validates_numericality_with_equal_to_using_differing_numeric_types - Topic.validates_numericality_of :approved, equal_to: BigDecimal.new('97.18') + Topic.validates_numericality_of :approved, equal_to: BigDecimal.new("97.18") - invalid!([-97.18, 97.18], 'must be equal to 97.18') - valid!([BigDecimal.new('97.18')]) + invalid!([-97.18], "must be equal to 97.18") + valid!([BigDecimal.new("97.18")]) end def test_validates_numericality_with_equal_to_using_string_value Topic.validates_numericality_of :approved, equal_to: 10 - invalid!(['-10', '9', '9.9', '10.1', '11'], 'must be equal to 10') - valid!(['10']) + invalid!(["-10", "9", "9.9", "10.1", "11"], "must be equal to 10") + valid!(["10"]) end def test_validates_numericality_with_less_than Topic.validates_numericality_of :approved, less_than: 10 - invalid!([10], 'must be less than 10') + invalid!([10], "must be less than 10") valid!([-9, 9]) end def test_validates_numericality_with_less_than_using_differing_numeric_types - Topic.validates_numericality_of :approved, less_than: BigDecimal.new('97.18') + Topic.validates_numericality_of :approved, less_than: BigDecimal.new("97.18") - invalid!([97.18, BigDecimal.new('97.18')], 'must be less than 97.18') - valid!([-97.0, 97.0, -97, 97, BigDecimal.new('-97'), BigDecimal.new('97')]) + invalid!([97.18, BigDecimal.new("97.18")], "must be less than 97.18") + valid!([-97.0, 97.0, -97, 97, BigDecimal.new("-97"), BigDecimal.new("97")]) end def test_validates_numericality_with_less_than_using_string_value Topic.validates_numericality_of :approved, less_than: 10 - invalid!(['10', '10.1', '11'], 'must be less than 10') - valid!(['-10', '9', '9.9']) + invalid!(["10", "10.1", "11"], "must be less than 10") + valid!(["-10", "9", "9.9"]) end def test_validates_numericality_with_less_than_or_equal_to Topic.validates_numericality_of :approved, less_than_or_equal_to: 10 - invalid!([11], 'must be less than or equal to 10') + invalid!([11], "must be less than or equal to 10") valid!([-10, 10]) end def test_validates_numericality_with_less_than_or_equal_to_using_differing_numeric_types - Topic.validates_numericality_of :approved, less_than_or_equal_to: BigDecimal.new('97.18') + Topic.validates_numericality_of :approved, less_than_or_equal_to: BigDecimal.new("97.18") - invalid!([97.18, 98], 'must be less than or equal to 97.18') - valid!([-97.18, BigDecimal.new('-97.18'), BigDecimal.new('97.18')]) + invalid!([97.19, 98], "must be less than or equal to 97.18") + valid!([-97.18, BigDecimal.new("-97.18"), BigDecimal.new("97.18")]) end def test_validates_numericality_with_less_than_or_equal_using_string_value Topic.validates_numericality_of :approved, less_than_or_equal_to: 10 - invalid!(['10.1', '11'], 'must be less than or equal to 10') - valid!(['-10', '9', '9.9', '10']) + invalid!(["10.1", "11"], "must be less than or equal to 10") + valid!(["-10", "9", "9.9", "10"]) end def test_validates_numericality_with_odd Topic.validates_numericality_of :approved, odd: true - invalid!([-2, 2], 'must be odd') + invalid!([-2, 2], "must be odd") valid!([-1, 1]) end def test_validates_numericality_with_even Topic.validates_numericality_of :approved, even: true - invalid!([-1, 1], 'must be even') + invalid!([-1, 1], "must be even") valid!([-2, 2]) end @@ -201,8 +207,8 @@ class NumericalityValidationTest < ActiveModel::TestCase def test_validates_numericality_with_other_than_using_string_value Topic.validates_numericality_of :approved, other_than: 0 - invalid!(['0', '0.0']) - valid!(['-1', '1.1', '42']) + invalid!(["0", "0.0"]) + valid!(["-1", "1.1", "42"]) end def test_validates_numericality_with_proc @@ -255,34 +261,34 @@ class NumericalityValidationTest < ActiveModel::TestCase end def test_validates_numericality_with_invalid_args - assert_raise(ArgumentError){ Topic.validates_numericality_of :approved, greater_than_or_equal_to: "foo" } - assert_raise(ArgumentError){ Topic.validates_numericality_of :approved, less_than_or_equal_to: "foo" } - assert_raise(ArgumentError){ Topic.validates_numericality_of :approved, greater_than: "foo" } - assert_raise(ArgumentError){ Topic.validates_numericality_of :approved, less_than: "foo" } - assert_raise(ArgumentError){ Topic.validates_numericality_of :approved, equal_to: "foo" } + assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, greater_than_or_equal_to: "foo" } + assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, less_than_or_equal_to: "foo" } + assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, greater_than: "foo" } + assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, less_than: "foo" } + assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, equal_to: "foo" } end private - def invalid!(values, error = nil) - with_each_topic_approved_value(values) do |topic, value| - assert topic.invalid?, "#{value.inspect} not rejected as a number" - assert topic.errors[:approved].any?, "FAILED for #{value.inspect}" - assert_equal error, topic.errors[:approved].first if error + def invalid!(values, error = nil) + with_each_topic_approved_value(values) do |topic, value| + assert topic.invalid?, "#{value.inspect} not rejected as a number" + assert topic.errors[:approved].any?, "FAILED for #{value.inspect}" + assert_equal error, topic.errors[:approved].first if error + end end - end - def valid!(values) - with_each_topic_approved_value(values) do |topic, value| - assert topic.valid?, "#{value.inspect} not accepted as a number with validation error: #{topic.errors[:approved].first}" + def valid!(values) + with_each_topic_approved_value(values) do |topic, value| + assert topic.valid?, "#{value.inspect} not accepted as a number with validation error: #{topic.errors[:approved].first}" + end end - end - def with_each_topic_approved_value(values) - topic = Topic.new(title: "numeric test", content: "whatever") - values.each do |value| - topic.approved = value - yield topic, value + def with_each_topic_approved_value(values) + topic = Topic.new(title: "numeric test", content: "whatever") + values.each do |value| + topic.approved = value + yield topic, value + end end - end end diff --git a/activemodel/test/cases/validations/presence_validation_test.rb b/activemodel/test/cases/validations/presence_validation_test.rb index 59b9db0795..642dd0f144 100644 --- a/activemodel/test/cases/validations/presence_validation_test.rb +++ b/activemodel/test/cases/validations/presence_validation_test.rb @@ -1,11 +1,10 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/person' -require 'models/custom_reader' +require "models/topic" +require "models/person" +require "models/custom_reader" class PresenceValidationTest < ActiveModel::TestCase - teardown do Topic.clear_validators! Person.clear_validators! @@ -21,7 +20,7 @@ class PresenceValidationTest < ActiveModel::TestCase assert_equal ["can't be blank"], t.errors[:content] t.title = "something" - t.content = " " + t.content = " " assert t.invalid? assert_equal ["can't be blank"], t.errors[:content] diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb index 04101f3545..011033606e 100644 --- a/activemodel/test/cases/validations/validates_test.rb +++ b/activemodel/test/cases/validations/validates_test.rb @@ -1,8 +1,8 @@ -require 'cases/helper' -require 'models/person' -require 'models/topic' -require 'models/person_with_validator' -require 'validators/namespace/email_validator' +require "cases/helper" +require "models/person" +require "models/topic" +require "models/person_with_validator" +require "validators/namespace/email_validator" class ValidatesTest < ActiveModel::TestCase setup :reset_callbacks @@ -17,21 +17,21 @@ class ValidatesTest < ActiveModel::TestCase def test_validates_with_messages_empty Person.validates :title, presence: { message: "" } person = Person.new - assert !person.valid?, 'person should not be valid.' + assert !person.valid?, "person should not be valid." end def test_validates_with_built_in_validation Person.validates :title, numericality: true person = Person.new person.valid? - assert_equal ['is not a number'], person.errors[:title] + assert_equal ["is not a number"], person.errors[:title] end def test_validates_with_attribute_specified_as_string Person.validates "title", numericality: true person = Person.new person.valid? - assert_equal ['is not a number'], person.errors[:title] + assert_equal ["is not a number"], person.errors[:title] person = Person.new person.title = 123 @@ -39,24 +39,24 @@ class ValidatesTest < ActiveModel::TestCase end def test_validates_with_built_in_validation_and_options - Person.validates :salary, numericality: { message: 'my custom message' } + Person.validates :salary, numericality: { message: "my custom message" } person = Person.new person.valid? - assert_equal ['my custom message'], person.errors[:salary] + assert_equal ["my custom message"], person.errors[:salary] end def test_validates_with_validator_class Person.validates :karma, email: true person = Person.new person.valid? - assert_equal ['is not an email'], person.errors[:karma] + assert_equal ["is not an email"], person.errors[:karma] end def test_validates_with_namespaced_validator_class - Person.validates :karma, :'namespace/email' => true + Person.validates :karma, 'namespace/email': true person = Person.new person.valid? - assert_equal ['is not an email'], person.errors[:karma] + assert_equal ["is not an email"], person.errors[:karma] end def test_validates_with_if_as_local_conditions @@ -89,7 +89,7 @@ class ValidatesTest < ActiveModel::TestCase Person.validates :karma, format: /positive|negative/ person = Person.new assert person.invalid? - assert_equal ['is invalid'], person.errors[:karma] + assert_equal ["is invalid"], person.errors[:karma] person.karma = "positive" assert person.valid? end @@ -98,7 +98,7 @@ class ValidatesTest < ActiveModel::TestCase Person.validates :gender, inclusion: %w(m f) person = Person.new assert person.invalid? - assert_equal ['is not included in the list'], person.errors[:gender] + assert_equal ["is not included in the list"], person.errors[:gender] person.gender = "m" assert person.valid? end @@ -107,16 +107,16 @@ class ValidatesTest < ActiveModel::TestCase Person.validates :karma, length: 6..20 person = Person.new assert person.invalid? - assert_equal ['is too short (minimum is 6 characters)'], person.errors[:karma] - person.karma = 'something' + assert_equal ["is too short (minimum is 6 characters)"], person.errors[:karma] + person.karma = "something" assert person.valid? end def test_validates_with_validator_class_and_options - Person.validates :karma, email: { message: 'my custom message' } + Person.validates :karma, email: { message: "my custom message" } person = Person.new person.valid? - assert_equal ['my custom message'], person.errors[:karma] + assert_equal ["my custom message"], person.errors[:karma] end def test_validates_with_unknown_validator @@ -127,14 +127,14 @@ class ValidatesTest < ActiveModel::TestCase PersonWithValidator.validates :title, presence: true person = PersonWithValidator.new person.valid? - assert_equal ['Local validator'], person.errors[:title] + assert_equal ["Local validator"], person.errors[:title] end def test_validates_with_included_validator_and_options - PersonWithValidator.validates :title, presence: { custom: ' please' } + PersonWithValidator.validates :title, presence: { custom: " please" } person = PersonWithValidator.new person.valid? - assert_equal ['Local validator please'], person.errors[:title] + assert_equal ["Local validator please"], person.errors[:title] end def test_validates_with_included_validator_and_wildcard_shortcut @@ -143,15 +143,15 @@ class ValidatesTest < ActiveModel::TestCase person = PersonWithValidator.new person.title = "Ms. Pacman" person.valid? - assert_equal ['does not appear to be like Mr.'], person.errors[:title] + assert_equal ["does not appear to be like Mr."], person.errors[:title] end def test_defining_extra_default_keys_for_validates - Topic.validates :title, confirmation: true, message: 'Y U NO CONFIRM' + Topic.validates :title, confirmation: true, message: "Y U NO CONFIRM" topic = Topic.new topic.title = "What's happening" topic.title_confirmation = "Not this" assert !topic.valid? - assert_equal ['Y U NO CONFIRM'], topic.errors[:title_confirmation] + assert_equal ["Y U NO CONFIRM"], topic.errors[:title_confirmation] end end diff --git a/activemodel/test/cases/validations/validations_context_test.rb b/activemodel/test/cases/validations/validations_context_test.rb index b901a1523e..25c37a572f 100644 --- a/activemodel/test/cases/validations/validations_context_test.rb +++ b/activemodel/test/cases/validations/validations_context_test.rb @@ -1,6 +1,6 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' +require "models/topic" class ValidationsContextTest < ActiveModel::TestCase def teardown @@ -38,7 +38,7 @@ class ValidationsContextTest < ActiveModel::TestCase Topic.validates_with(ValidatorThatAddsErrors, on: :create) topic = Topic.new assert topic.invalid?(:create), "Validation does run on create if 'on' is set to create" - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE end test "with a class that adds errors on multiple contexts and validating a new model" do @@ -48,10 +48,10 @@ class ValidationsContextTest < ActiveModel::TestCase assert topic.valid?, "Validation ran with no context given when 'on' is set to context1 and context2" assert topic.invalid?(:context1), "Validation did not run on context1 when 'on' is set to context1 and context2" - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE assert topic.invalid?(:context2), "Validation did not run on context2 when 'on' is set to context1 and context2" - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE end test "with a class that validating a model for a multiple contexts" do @@ -62,7 +62,7 @@ class ValidationsContextTest < ActiveModel::TestCase assert topic.valid?, "Validation ran with no context given when 'on' is set to context1 and context2" assert topic.invalid?([:context1, :context2]), "Validation did not run on context1 when 'on' is set to context1 and context2" - assert topic.errors[:base].include?(ERROR_MESSAGE) - assert topic.errors[:base].include?(ANOTHER_ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE + assert_includes topic.errors[:base], ANOTHER_ERROR_MESSAGE end end diff --git a/activemodel/test/cases/validations/with_validation_test.rb b/activemodel/test/cases/validations/with_validation_test.rb index c73580138d..20c11dd852 100644 --- a/activemodel/test/cases/validations/with_validation_test.rb +++ b/activemodel/test/cases/validations/with_validation_test.rb @@ -1,9 +1,8 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' +require "models/topic" class ValidatesWithTest < ActiveModel::TestCase - def teardown Topic.clear_validators! end @@ -52,7 +51,7 @@ class ValidatesWithTest < ActiveModel::TestCase Topic.validates_with(ValidatorThatAddsErrors) topic = Topic.new assert topic.invalid?, "A class that adds errors causes the record to be invalid" - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE end test "with a class that returns valid" do @@ -65,8 +64,8 @@ class ValidatesWithTest < ActiveModel::TestCase Topic.validates_with(ValidatorThatAddsErrors, OtherValidatorThatAddsErrors) topic = Topic.new assert topic.invalid? - assert topic.errors[:base].include?(ERROR_MESSAGE) - assert topic.errors[:base].include?(OTHER_ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE + assert_includes topic.errors[:base], OTHER_ERROR_MESSAGE end test "with if statements that return false" do @@ -79,7 +78,7 @@ class ValidatesWithTest < ActiveModel::TestCase Topic.validates_with(ValidatorThatAddsErrors, if: "1 == 1") topic = Topic.new assert topic.invalid? - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE end test "with unless statements that return true" do @@ -92,13 +91,13 @@ class ValidatesWithTest < ActiveModel::TestCase Topic.validates_with(ValidatorThatAddsErrors, unless: "1 == 2") topic = Topic.new assert topic.invalid? - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE end test "passes all configuration options to the validator class" do topic = Topic.new validator = Minitest::Mock.new - validator.expect(:new, validator, [{foo: :bar, if: "1 == 1", class: Topic}]) + validator.expect(:new, validator, [{ foo: :bar, if: "1 == 1", class: Topic }]) validator.expect(:validate, nil, [topic]) validator.expect(:is_a?, false, [Symbol]) validator.expect(:is_a?, false, [String]) @@ -112,7 +111,7 @@ class ValidatesWithTest < ActiveModel::TestCase Topic.validates_with(ValidatorThatValidatesOptions, field: :first_name) topic = Topic.new assert topic.invalid? - assert topic.errors[:base].include?(ERROR_MESSAGE) + assert_includes topic.errors[:base], ERROR_MESSAGE end test "validates_with each validator" do @@ -160,7 +159,7 @@ class ValidatesWithTest < ActiveModel::TestCase topic = Topic.new assert !topic.valid? - assert_equal ['is missing'], topic.errors[:title] + assert_equal ["is missing"], topic.errors[:title] end test "optionally pass in the attribute being validated when validating with an instance method" do @@ -169,6 +168,6 @@ class ValidatesWithTest < ActiveModel::TestCase topic = Topic.new title: "foo" assert !topic.valid? assert topic.errors[:title].empty? - assert_equal ['is missing'], topic.errors[:content] + assert_equal ["is missing"], topic.errors[:content] end end diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb index 2a4e9f842f..6647191205 100644 --- a/activemodel/test/cases/validations_test.rb +++ b/activemodel/test/cases/validations_test.rb @@ -1,11 +1,11 @@ -require 'cases/helper' +require "cases/helper" -require 'models/topic' -require 'models/reply' -require 'models/custom_reader' +require "models/topic" +require "models/reply" +require "models/custom_reader" -require 'active_support/json' -require 'active_support/xml_mini' +require "active_support/json" +require "active_support/xml_mini" class ValidationsTest < ActiveModel::TestCase class CustomStrictValidationException < StandardError; end @@ -51,10 +51,10 @@ class ValidationsTest < ActiveModel::TestCase r = Reply.new r.valid? - errors = r.errors.collect {|attr, messages| [attr.to_s, messages]} + errors = r.errors.collect { |attr, messages| [attr.to_s, messages] } - assert errors.include?(["title", "is Empty"]) - assert errors.include?(["content", "is Empty"]) + assert_includes errors, ["title", "is Empty"] + assert_includes errors, ["content", "is Empty"] end def test_multiple_errors_per_attr_iteration_with_full_error_composition @@ -86,8 +86,8 @@ class ValidationsTest < ActiveModel::TestCase assert_equal ["Reply is not dignifying"], r.errors[:base] - assert errors.include?("Title is Empty") - assert errors.include?("Reply is not dignifying") + assert_includes errors, "Title is Empty" + assert_includes errors, "Reply is not dignifying" assert_equal 2, r.errors.count end @@ -101,8 +101,8 @@ class ValidationsTest < ActiveModel::TestCase assert_equal ["is invalid"], r.errors[:base] - assert errors.include?("Title is Empty") - assert errors.include?("is invalid") + assert_includes errors, "Title is Empty" + assert_includes errors, "is invalid" assert_equal 2, r.errors.count end @@ -116,7 +116,7 @@ class ValidationsTest < ActiveModel::TestCase def test_validates_each hits = 0 Topic.validates_each(:title, :content, [:title, :content]) do |record, attr| - record.errors.add attr, 'gotcha' + record.errors.add attr, "gotcha" hits += 1 end t = Topic.new("title" => "valid", "content" => "whatever") @@ -129,7 +129,7 @@ class ValidationsTest < ActiveModel::TestCase def test_validates_each_custom_reader hits = 0 CustomReader.validates_each(:title, :content, [:title, :content]) do |record, attr| - record.errors.add attr, 'gotcha' + record.errors.add attr, "gotcha" hits += 1 end t = CustomReader.new("title" => "valid", "content" => "whatever") @@ -170,7 +170,7 @@ class ValidationsTest < ActiveModel::TestCase # A common mistake -- we meant to call 'validates' Topic.validate :title, presence: true end - message = 'Unknown key: :presence. Valid keys are: :on, :if, :unless, :prepend. Perhaps you meant to call `validates` instead of `validate`?' + message = "Unknown key: :presence. Valid keys are: :on, :if, :unless, :prepend. Perhaps you meant to call `validates` instead of `validate`?" assert_equal message, error.message end @@ -198,9 +198,9 @@ class ValidationsTest < ActiveModel::TestCase end assert_nothing_raised do - klass.validate :validator_a, if: ->{ true } + klass.validate :validator_a, if: -> { true } klass.validate :validator_b, prepend: true - klass.validate :validator_c, unless: ->{ true } + klass.validate :validator_c, unless: -> { true } end t = klass.new @@ -233,25 +233,25 @@ class ValidationsTest < ActiveModel::TestCase assert t.invalid? assert_equal "can't be blank", t.errors["title"].first Topic.validates_presence_of :title, :author_name - Topic.validate {errors.add('author_email_address', 'will never be valid')} + Topic.validate { errors.add("author_email_address", "will never be valid") } Topic.validates_length_of :title, :content, minimum: 2 - t = Topic.new title: '' + t = Topic.new title: "" assert t.invalid? assert_equal :title, key = t.errors.keys[0] assert_equal "can't be blank", t.errors[key][0] - assert_equal 'is too short (minimum is 2 characters)', t.errors[key][1] + assert_equal "is too short (minimum is 2 characters)", t.errors[key][1] assert_equal :author_name, key = t.errors.keys[1] assert_equal "can't be blank", t.errors[key][0] assert_equal :author_email_address, key = t.errors.keys[2] - assert_equal 'will never be valid', t.errors[key][0] + assert_equal "will never be valid", t.errors[key][0] assert_equal :content, key = t.errors.keys[3] - assert_equal 'is too short (minimum is 2 characters)', t.errors[key][0] + assert_equal "is too short (minimum is 2 characters)", t.errors[key][0] end def test_validation_with_if_and_on - Topic.validates_presence_of :title, if: Proc.new{|x| x.author_name = "bad"; true }, on: :update + Topic.validates_presence_of :title, if: Proc.new { |x| x.author_name = "bad"; true }, on: :update t = Topic.new(title: "") @@ -271,7 +271,7 @@ class ValidationsTest < ActiveModel::TestCase assert t.invalid? assert t.errors[:title].any? - t.title = 'Things are going to change' + t.title = "Things are going to change" assert !t.invalid? end @@ -332,9 +332,9 @@ class ValidationsTest < ActiveModel::TestCase assert topic.invalid? assert_equal 3, topic.errors.size - topic.title = 'Some Title' - topic.author_name = 'Some Author' - topic.content = 'Some Content Whose Length is more than 10.' + topic.title = "Some Title" + topic.author_name = "Some Author" + topic.content = "Some Content Whose Length is more than 10." assert topic.valid? end @@ -440,7 +440,7 @@ class ValidationsTest < ActiveModel::TestCase assert duped.invalid? topic.title = nil - duped.title = 'Mathematics' + duped.title = "Mathematics" assert topic.invalid? assert duped.valid? end @@ -448,7 +448,7 @@ class ValidationsTest < ActiveModel::TestCase def test_validation_with_message_as_proc_that_takes_a_record_as_a_parameter Topic.validates_presence_of(:title, message: proc { |record| "You have failed me for the last time, #{record.author_name}." }) - t = Topic.new(author_name: 'Admiral') + t = Topic.new(author_name: "Admiral") assert t.invalid? assert_equal ["You have failed me for the last time, Admiral."], t.errors[:title] end @@ -456,7 +456,7 @@ class ValidationsTest < ActiveModel::TestCase def test_validation_with_message_as_proc_that_takes_record_and_data_as_a_parameters Topic.validates_presence_of(:title, message: proc { |record, data| "#{data[:attribute]} is missing. You have failed me for the last time, #{record.author_name}." }) - t = Topic.new(author_name: 'Admiral') + t = Topic.new(author_name: "Admiral") assert t.invalid? assert_equal ["Title is missing. You have failed me for the last time, Admiral."], t.errors[:title] end diff --git a/activemodel/test/models/custom_reader.rb b/activemodel/test/models/custom_reader.rb index 2fbcf79c3d..dc26bb10ff 100644 --- a/activemodel/test/models/custom_reader.rb +++ b/activemodel/test/models/custom_reader.rb @@ -12,4 +12,4 @@ class CustomReader def read_attribute_for_validation(key) @data[key] end -end
\ No newline at end of file +end diff --git a/activemodel/test/models/reply.rb b/activemodel/test/models/reply.rb index b77910e671..3fe11043d2 100644 --- a/activemodel/test/models/reply.rb +++ b/activemodel/test/models/reply.rb @@ -1,4 +1,4 @@ -require 'models/topic' +require "models/topic" class Reply < Topic validate :errors_on_empty_content diff --git a/activemodel/test/models/topic.rb b/activemodel/test/models/topic.rb index fed50bc361..192786c096 100644 --- a/activemodel/test/models/topic.rb +++ b/activemodel/test/models/topic.rb @@ -36,9 +36,4 @@ class Topic def my_validation_with_arg(attr) errors.add attr, "is missing" unless send(attr) end - - def my_word_tokenizer(str) - str.scan(/\w+/) - end - end diff --git a/activemodel/test/models/track_back.rb b/activemodel/test/models/track_back.rb index 768c96ecf0..357ee37d6d 100644 --- a/activemodel/test/models/track_back.rb +++ b/activemodel/test/models/track_back.rb @@ -8,4 +8,4 @@ class Post class NamedTrackBack extend ActiveModel::Naming end -end
\ No newline at end of file +end diff --git a/activemodel/test/models/user.rb b/activemodel/test/models/user.rb index 1ec6001c48..6556b1a7d9 100644 --- a/activemodel/test/models/user.rb +++ b/activemodel/test/models/user.rb @@ -1,7 +1,7 @@ class User extend ActiveModel::Callbacks include ActiveModel::SecurePassword - + define_model_callbacks :create has_secure_password diff --git a/activemodel/test/validators/email_validator.rb b/activemodel/test/validators/email_validator.rb index cff47ac230..9b74d83b37 100644 --- a/activemodel/test/validators/email_validator.rb +++ b/activemodel/test/validators/email_validator.rb @@ -1,6 +1,7 @@ + class EmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) record.errors[attribute] << (options[:message] || "is not an email") unless - value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i + /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value) end -end
\ No newline at end of file +end diff --git a/activemodel/test/validators/namespace/email_validator.rb b/activemodel/test/validators/namespace/email_validator.rb index 57e2793ce2..8639045b0d 100644 --- a/activemodel/test/validators/namespace/email_validator.rb +++ b/activemodel/test/validators/namespace/email_validator.rb @@ -1,4 +1,4 @@ -require 'validators/email_validator' +require "validators/email_validator" module Namespace class EmailValidator < ::EmailValidator |