aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb2
-rw-r--r--actionview/lib/action_view/helpers/asset_tag_helper.rb9
-rw-r--r--actionview/lib/action_view/helpers/asset_url_helper.rb23
-rw-r--r--actionview/lib/action_view/helpers/translation_helper.rb3
-rw-r--r--actionview/lib/action_view/helpers/url_helper.rb3
-rw-r--r--actionview/lib/action_view/layouts.rb7
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb5
-rw-r--r--actionview/lib/action_view/renderer/template_renderer.rb2
-rw-r--r--actionview/lib/action_view/template/error.rb3
-rw-r--r--actionview/lib/action_view/template/handlers/erb.rb5
-rw-r--r--actionview/lib/action_view/testing/resolvers.rb4
-rw-r--r--actionview/test/actionpack/controller/layout_test.rb3
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb5
-rw-r--r--activemodel/lib/active_model/type/time.rb2
-rw-r--r--activemodel/lib/active_model/validations/format.rb5
-rw-r--r--activemodel/test/validators/email_validator.rb6
-rw-r--r--activerecord/CHANGELOG.md5
-rw-r--r--activerecord/Rakefile4
-rw-r--r--activerecord/lib/active_record/attribute.rb4
-rw-r--r--activerecord/lib/active_record/attribute_set.rb2
-rw-r--r--activerecord/lib/active_record/attribute_set/builder.rb28
-rw-r--r--activerecord/lib/active_record/attributes.rb2
-rw-r--r--activerecord/lib/active_record/coders/yaml_column.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb2
-rw-r--r--activerecord/lib/active_record/dynamic_matchers.rb4
-rw-r--r--activerecord/lib/active_record/migration.rb5
-rw-r--r--activerecord/lib/active_record/model_schema.rb13
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb3
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb9
-rw-r--r--activerecord/lib/active_record/sanitization.rb4
-rw-r--r--activerecord/lib/active_record/tasks/mysql_database_tasks.rb2
-rw-r--r--activerecord/lib/rails/generators/active_record/migration/migration_generator.rb3
-rw-r--r--activerecord/test/cases/associations/inner_join_association_test.rb2
-rw-r--r--activerecord/test/cases/associations/left_outer_join_association_test.rb11
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb307
-rw-r--r--activerecord/test/cases/attributes_test.rb44
-rw-r--r--activerecord/test/cases/callbacks_test.rb2
-rw-r--r--activerecord/test/cases/dirty_test.rb2
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb3
-rw-r--r--activerecord/test/cases/test_case.rb3
-rw-r--r--activerecord/test/schema/postgresql_specific_schema.rb2
-rw-r--r--guides/source/caching_with_rails.md2
44 files changed, 333 insertions, 230 deletions
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 3f0e51790c..ea0e2ee41f 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -65,7 +65,7 @@ module ActionDispatch
private
def parse_formatted_parameters(parsers)
- return yield if content_length.zero?
+ return yield if content_length.zero? || content_mime_type.nil?
strategy = parsers.fetch(content_mime_type.symbol) { return yield }
diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb
index bcbb3db6a9..d7acf08b45 100644
--- a/actionview/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/hash/keys'
+require 'active_support/core_ext/regexp'
require 'action_view/helpers/asset_url_helper'
require 'action_view/helpers/tag_helper'
@@ -213,8 +214,8 @@ module ActionView
src = options[:src] = path_to_image(source)
- unless src =~ /^(?:cid|data):/ || src.blank?
- options[:alt] = options.fetch(:alt){ image_alt(src) }
+ unless src.start_with?('cid:') || src.start_with?('data:') || src.blank?
+ options[:alt] = options.fetch(:alt) { image_alt(src) }
end
options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
@@ -322,9 +323,9 @@ module ActionView
def extract_dimensions(size)
size = size.to_s
- if size =~ %r{\A\d+x\d+\z}
+ if /\A\d+x\d+\z/.match?(size)
size.split('x')
- elsif size =~ %r{\A\d+\z}
+ elsif /\A\d+\z/.match?(size)
[size, size]
end
end
diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb
index 717b326740..8af01617fa 100644
--- a/actionview/lib/action_view/helpers/asset_url_helper.rb
+++ b/actionview/lib/action_view/helpers/asset_url_helper.rb
@@ -1,4 +1,5 @@
require 'zlib'
+require 'active_support/core_ext/regexp'
module ActionView
# = Action View Asset URL Helpers
@@ -131,8 +132,8 @@ module ActionView
raise ArgumentError, "nil is not a valid asset source" if source.nil?
source = source.to_s
- return "" unless source.present?
- return source if source =~ URI_REGEXP
+ return '' if source.blank?
+ return source if URI_REGEXP.match?(source)
tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, ''.freeze)
@@ -213,19 +214,21 @@ module ActionView
host = options[:host]
host ||= config.asset_host if defined? config.asset_host
- if host.respond_to?(:call)
- arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
- args = [source]
- args << request if request && (arity > 1 || arity < 0)
- host = host.call(*args)
- elsif host =~ /%d/
- host = host % (Zlib.crc32(source) % 4)
+ if host
+ if host.respond_to?(:call)
+ arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
+ args = [source]
+ args << request if request && (arity > 1 || arity < 0)
+ host = host.call(*args)
+ elsif host.include?('%d')
+ host = host % (Zlib.crc32(source) % 4)
+ end
end
host ||= request.base_url if request && options[:protocol] == :request
return unless host
- if host =~ URI_REGEXP
+ if URI_REGEXP.match?(host)
host
else
protocol = options[:protocol] || config.default_asset_host_protocol || (request ? :request : :relative)
diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb
index 152e1b1211..622bb193ae 100644
--- a/actionview/lib/action_view/helpers/translation_helper.rb
+++ b/actionview/lib/action_view/helpers/translation_helper.rb
@@ -1,5 +1,6 @@
require 'action_view/helpers/tag_helper'
require 'active_support/core_ext/string/access'
+require 'active_support/core_ext/regexp'
require 'i18n/exceptions'
module ActionView
@@ -133,7 +134,7 @@ module ActionView
end
def html_safe_translation_key?(key)
- key.to_s =~ /(\b|_|\.)html$/
+ /(\b|_|\.)html$/.match?(key.to_s)
end
end
end
diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb
index fb6426b997..5d7940a7b1 100644
--- a/actionview/lib/action_view/helpers/url_helper.rb
+++ b/actionview/lib/action_view/helpers/url_helper.rb
@@ -2,6 +2,7 @@ require 'action_view/helpers/javascript_helper'
require 'active_support/core_ext/array/access'
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/string/output_safety'
+require 'active_support/core_ext/regexp'
module ActionView
# = Action View URL Helpers
@@ -550,7 +551,7 @@ module ActionView
url_string.chomp!("/") if url_string.start_with?("/") && url_string != "/"
- if url_string =~ /^\w+:\/\//
+ if %r{^\w+://}.match?(url_string)
url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
else
url_string == request_uri
diff --git a/actionview/lib/action_view/layouts.rb b/actionview/lib/action_view/layouts.rb
index 8db1674187..8e956c47c6 100644
--- a/actionview/lib/action_view/layouts.rb
+++ b/actionview/lib/action_view/layouts.rb
@@ -1,5 +1,6 @@
-require "action_view/rendering"
-require "active_support/core_ext/module/remove_method"
+require 'action_view/rendering'
+require 'active_support/core_ext/module/remove_method'
+require 'active_support/core_ext/regexp'
module ActionView
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
@@ -279,7 +280,7 @@ module ActionView
def _write_layout_method # :nodoc:
remove_possible_method(:_layout)
- prefixes = _implied_layout_name =~ /\blayouts/ ? [] : ["layouts"]
+ prefixes = /\blayouts/.match?(_implied_layout_name) ? [] : ["layouts"]
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}, false, [], { formats: formats }).first || super"
name_clause = if name
default_behavior
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index 13b4ec6133..c2b15e72e9 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -1,5 +1,6 @@
-require 'action_view/renderer/partial_renderer/collection_caching'
require 'concurrent/map'
+require 'active_support/core_ext/regexp'
+require 'action_view/renderer/partial_renderer/collection_caching'
module ActionView
class PartialIteration
@@ -386,7 +387,7 @@ module ActionView
end
if as = options[:as]
- raise_invalid_option_as(as) unless as.to_s =~ /\A[a-z_]\w*\z/
+ raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)
as = as.to_sym
end
diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb
index 1d6afb90fe..9b106cd64a 100644
--- a/actionview/lib/action_view/renderer/template_renderer.rb
+++ b/actionview/lib/action_view/renderer/template_renderer.rb
@@ -83,7 +83,7 @@ module ActionView
case layout
when String
begin
- if layout =~ /^\//
+ if layout.start_with?('/')
with_fallbacks { find_template(layout, nil, false, [], details) }
else
find_template(layout, nil, false, [], details)
diff --git a/actionview/lib/action_view/template/error.rb b/actionview/lib/action_view/template/error.rb
index 3f38c3d2b9..0f1348b032 100644
--- a/actionview/lib/action_view/template/error.rb
+++ b/actionview/lib/action_view/template/error.rb
@@ -1,4 +1,5 @@
require "active_support/core_ext/enumerable"
+require 'active_support/core_ext/regexp'
module ActionView
# = Action View Errors
@@ -35,7 +36,7 @@ module ActionView
prefixes = Array(prefixes)
template_type = if partial
"partial"
- elsif path =~ /layouts/i
+ elsif /layouts/i.match?(path)
'layout'
else
'template'
diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb
index 85a100ed4c..058b590c56 100644
--- a/actionview/lib/action_view/template/handlers/erb.rb
+++ b/actionview/lib/action_view/template/handlers/erb.rb
@@ -1,4 +1,5 @@
require 'erubis'
+require 'active_support/core_ext/regexp'
module ActionView
class Template
@@ -39,7 +40,7 @@ module ActionView
def add_expr_literal(src, code)
flush_newline_if_pending(src)
- if code =~ BLOCK_EXPR
+ if BLOCK_EXPR.match?(code)
src << '@output_buffer.append= ' << code
else
src << '@output_buffer.append=(' << code << ');'
@@ -48,7 +49,7 @@ module ActionView
def add_expr_escaped(src, code)
flush_newline_if_pending(src)
- if code =~ BLOCK_EXPR
+ if BLOCK_EXPR.match?(code)
src << "@output_buffer.safe_expr_append= " << code
else
src << "@output_buffer.safe_expr_append=(" << code << ");"
diff --git a/actionview/lib/action_view/testing/resolvers.rb b/actionview/lib/action_view/testing/resolvers.rb
index 2664aca991..982ecf9efc 100644
--- a/actionview/lib/action_view/testing/resolvers.rb
+++ b/actionview/lib/action_view/testing/resolvers.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext/regexp'
require 'action_view/template/resolver'
module ActionView #:nodoc:
@@ -29,7 +30,7 @@ module ActionView #:nodoc:
templates = []
@hash.each do |_path, array|
source, updated_at = array
- next unless _path =~ query
+ next unless query.match?(_path)
handler, format, variant = extract_handler_and_format_and_variant(_path, formats)
templates << Template.new(source, _path, handler,
:virtual_path => path.virtual,
@@ -50,4 +51,3 @@ module ActionView #:nodoc:
end
end
end
-
diff --git a/actionview/test/actionpack/controller/layout_test.rb b/actionview/test/actionpack/controller/layout_test.rb
index 64bc4c41d6..ecfef3dc8c 100644
--- a/actionview/test/actionpack/controller/layout_test.rb
+++ b/actionview/test/actionpack/controller/layout_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/core_ext/array/extract_options'
+require 'active_support/core_ext/regexp'
# The view_paths array must be set on Base and not LayoutTest so that LayoutTest's inherited
# method has access to the view_paths array when looking for a layout to automatically assign.
@@ -252,7 +253,7 @@ class LayoutStatusIsRenderedTest < ActionController::TestCase
end
end
-unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
+unless /mswin|mingw/.match?(RbConfig::CONFIG['host_os'])
class LayoutSymlinkedTest < LayoutTest
layout "symlinked/symlinked_layout"
end
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index cc6285f932..140eb9420e 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -1,5 +1,6 @@
require 'concurrent/map'
require 'mutex_m'
+require 'active_support/core_ext/regexp'
module ActiveModel
# Raised when an attribute is not defined.
@@ -366,7 +367,7 @@ module ActiveModel
# 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
+ defn = if NAME_COMPILABLE_REGEXP.match?(name)
"def #{name}(*args)"
else
"define_method(:'#{name}') do |*args|"
@@ -374,7 +375,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})"
diff --git a/activemodel/lib/active_model/type/time.rb b/activemodel/lib/active_model/type/time.rb
index 34e09f0aba..08d127d187 100644
--- a/activemodel/lib/active_model/type/time.rb
+++ b/activemodel/lib/active_model/type/time.rb
@@ -29,7 +29,7 @@ module ActiveModel
return value unless value.is_a?(::String)
return if value.empty?
- if value =~ /^2000-01-01/
+ if value.start_with?('2000-01-01')
dummy_time_value = value
else
dummy_time_value = "2000-01-01 #{value}"
diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb
index 46a2e54fba..70799aaf23 100644
--- a/activemodel/lib/active_model/validations/format.rb
+++ b/activemodel/lib/active_model/validations/format.rb
@@ -1,5 +1,6 @@
-module ActiveModel
+require 'active_support/core_ext/regexp'
+module ActiveModel
module Validations
class FormatValidator < EachValidator # :nodoc:
def validate_each(record, attribute, value)
@@ -8,7 +9,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
diff --git a/activemodel/test/validators/email_validator.rb b/activemodel/test/validators/email_validator.rb
index cff47ac230..5dc1fc5ae2 100644
--- a/activemodel/test/validators/email_validator.rb
+++ b/activemodel/test/validators/email_validator.rb
@@ -1,6 +1,8 @@
+require 'active_support/core_ext/regexp'
+
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/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 590fe2f587..d3e1cf68a2 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Virtual attributes will no longer raise when read on models loaded from the
+ database
+
+ *Sean Griffin*
+
* Support calling the method `merge` in `scope`'s lambda.
*Yasuhiro Sugino*
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 012db35765..8fbea61335 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -51,7 +51,7 @@ end
adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
t.libs << 'test'
t.test_files = (Dir.glob( "test/cases/**/*_test.rb" ).reject {
- |x| x =~ /\/adapters\//
+ |x| x.include?('/adapters/')
} + Dir.glob("test/cases/adapters/#{adapter_short}/**/*_test.rb"))
t.warning = true
@@ -64,7 +64,7 @@ end
adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
puts [adapter, adapter_short].inspect
(Dir["test/cases/**/*_test.rb"].reject {
- |x| x =~ /\/adapters\//
+ |x| x.include?('/adapters/')
} + Dir["test/cases/adapters/#{adapter_short}/**/*_test.rb"]).all? do |file|
sh(Gem.ruby, '-w' ,"-Itest", file)
end or raise "Failures"
diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb
index 9530f134d0..2f41e9e45b 100644
--- a/activerecord/lib/active_record/attribute.rb
+++ b/activerecord/lib/active_record/attribute.rb
@@ -152,7 +152,7 @@ module ActiveRecord
end
def _original_value_for_database
- value_for_database
+ type.serialize(original_value)
end
class FromDatabase < Attribute # :nodoc:
@@ -180,7 +180,7 @@ module ActiveRecord
value
end
- def changed_in_place_from?(old_value)
+ def changed_in_place?
false
end
end
diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb
index 720d5f8b7c..f868f23845 100644
--- a/activerecord/lib/active_record/attribute_set.rb
+++ b/activerecord/lib/active_record/attribute_set.rb
@@ -3,7 +3,7 @@ require 'active_record/attribute_set/yaml_encoder'
module ActiveRecord
class AttributeSet # :nodoc:
- delegate :each_value, to: :attributes
+ delegate :each_value, :fetch, to: :attributes
def initialize(attributes)
@attributes = attributes
diff --git a/activerecord/lib/active_record/attribute_set/builder.rb b/activerecord/lib/active_record/attribute_set/builder.rb
index 24a255efc1..4ffd39d82d 100644
--- a/activerecord/lib/active_record/attribute_set/builder.rb
+++ b/activerecord/lib/active_record/attribute_set/builder.rb
@@ -3,11 +3,12 @@ require 'active_record/attribute'
module ActiveRecord
class AttributeSet # :nodoc:
class Builder # :nodoc:
- attr_reader :types, :always_initialized
+ attr_reader :types, :always_initialized, :default
- def initialize(types, always_initialized = nil)
+ def initialize(types, always_initialized = nil, &default)
@types = types
@always_initialized = always_initialized
+ @default = default
end
def build_from_database(values = {}, additional_types = {})
@@ -15,21 +16,22 @@ module ActiveRecord
values[always_initialized] = nil
end
- attributes = LazyAttributeHash.new(types, values, additional_types)
+ attributes = LazyAttributeHash.new(types, values, additional_types, &default)
AttributeSet.new(attributes)
end
end
end
class LazyAttributeHash # :nodoc:
- delegate :transform_values, :each_key, :each_value, to: :materialize
+ delegate :transform_values, :each_key, :each_value, :fetch, to: :materialize
- def initialize(types, values, additional_types)
+ def initialize(types, values, additional_types, &default)
@types = types
@values = values
@additional_types = additional_types
@materialized = false
@delegate_hash = {}
+ @default = default || proc {}
end
def key?(key)
@@ -76,9 +78,21 @@ module ActiveRecord
end
end
+ def marshal_dump
+ materialize
+ end
+
+ def marshal_load(delegate_hash)
+ @delegate_hash = delegate_hash
+ @types = {}
+ @values = {}
+ @additional_types = {}
+ @materialized = true
+ end
+
protected
- attr_reader :types, :values, :additional_types, :delegate_hash
+ attr_reader :types, :values, :additional_types, :delegate_hash, :default
def materialize
unless @materialized
@@ -101,7 +115,7 @@ module ActiveRecord
if value_present
delegate_hash[name] = Attribute.from_database(name, value, type)
elsif types.key?(name)
- delegate_hash[name] = Attribute.uninitialized(name, type)
+ delegate_hash[name] = default.call(name) || Attribute.uninitialized(name, type)
end
end
end
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
index 3211b6eaeb..ed0302e763 100644
--- a/activerecord/lib/active_record/attributes.rb
+++ b/activerecord/lib/active_record/attributes.rb
@@ -253,7 +253,7 @@ module ActiveRecord
name,
value,
type,
- _default_attributes[name],
+ _default_attributes.fetch(name.to_s) { nil },
)
else
default_attribute = Attribute.from_database(name, value, type)
diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb
index 2456b8ad8c..5ac1e0c001 100644
--- a/activerecord/lib/active_record/coders/yaml_column.rb
+++ b/activerecord/lib/active_record/coders/yaml_column.rb
@@ -1,4 +1,5 @@
require 'yaml'
+require 'active_support/core_ext/regexp'
module ActiveRecord
module Coders # :nodoc:
@@ -20,7 +21,7 @@ module ActiveRecord
def load(yaml)
return object_class.new if object_class != Object && yaml.nil?
- return yaml unless yaml.is_a?(String) && yaml =~ /^---/
+ return yaml unless yaml.is_a?(String) && /^---/.match?(yaml)
obj = YAML.load(yaml)
assert_valid_value(obj)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 3e77b92141..25e3939b62 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -9,6 +9,7 @@ require 'active_record/connection_adapters/mysql/schema_dumper'
require 'active_record/connection_adapters/mysql/type_metadata'
require 'active_support/core_ext/string/strip'
+require 'active_support/core_ext/regexp'
module ActiveRecord
module ConnectionAdapters
@@ -85,7 +86,7 @@ module ActiveRecord
end
def mariadb? # :nodoc:
- full_version =~ /mariadb/i
+ /mariadb/i.match?(full_version)
end
# Returns true, since this connection adapter supports migrations.
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index 6414459cd1..80c219dfd7 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -58,7 +58,7 @@ module ActiveRecord
def quote_default_expression(value, column) # :nodoc:
if value.is_a?(Proc)
value.call
- elsif column.type == :uuid && value =~ /\(\)/
+ elsif column.type == :uuid && value.include?('()')
value # Does not quote function default values for UUID columns
elsif column.respond_to?(:array?)
value = type_cast_from_column(column, value)
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 7e23f44ddf..ed6bff4665 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -548,7 +548,7 @@ module ActiveRecord
columns_string.split(',').each do |column_string|
# This regex will match the column name and collation type and will save
# the value in $1 and $2 respectively.
- collation_hash[$1] = $2 if (COLLATE_REGEX =~ column_string)
+ collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
end
basic_structure.map! do |column|
diff --git a/activerecord/lib/active_record/dynamic_matchers.rb b/activerecord/lib/active_record/dynamic_matchers.rb
index b6dd6814db..0bdebb3989 100644
--- a/activerecord/lib/active_record/dynamic_matchers.rb
+++ b/activerecord/lib/active_record/dynamic_matchers.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/regexp'
+
module ActiveRecord
module DynamicMatchers #:nodoc:
def respond_to?(name, include_private = false)
@@ -29,7 +31,7 @@ module ActiveRecord
attr_reader :matchers
def match(model, name)
- klass = matchers.find { |k| name =~ k.pattern }
+ klass = matchers.find { |k| k.pattern.match?(name) }
klass.new(model, name) if klass
end
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index fb2a23b797..1bb4688717 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -1,5 +1,6 @@
-require "active_support/core_ext/module/attribute_accessors"
require 'set'
+require "active_support/core_ext/module/attribute_accessors"
+require 'active_support/core_ext/regexp'
module ActiveRecord
class MigrationError < ActiveRecordError#:nodoc:
@@ -1057,7 +1058,7 @@ module ActiveRecord
end
def match_to_migration_filename?(filename) # :nodoc:
- File.basename(filename) =~ Migration::MigrationFilenameRegexp
+ Migration::MigrationFilenameRegexp.match?(File.basename(filename))
end
def parse_migration_filename(filename) # :nodoc:
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index 114686c5d3..41cebb0e34 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -249,7 +249,11 @@ module ActiveRecord
end
def attributes_builder # :nodoc:
- @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key)
+ @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key) do |name|
+ unless columns_hash.key?(name)
+ _default_attributes[name].dup
+ end
+ end
end
def columns_hash # :nodoc:
@@ -309,7 +313,12 @@ module ActiveRecord
# Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
# and columns used for single table inheritance have been removed.
def content_columns
- @content_columns ||= columns.reject { |c| c.name == primary_key || c.name =~ /(_id|_count)$/ || c.name == inheritance_column }
+ @content_columns ||= columns.reject do |c|
+ c.name == primary_key ||
+ c.name == inheritance_column ||
+ c.name.end_with?('_id') ||
+ c.name.end_with?('_count')
+ end
end
# Resets all the cached information about columns, which will cause them
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index 2484cb3264..ad74659cba 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -1,4 +1,5 @@
require 'active_support/concern'
+require 'active_support/core_ext/regexp'
module ActiveRecord
module Delegation # :nodoc:
@@ -58,7 +59,7 @@ module ActiveRecord
@delegation_mutex.synchronize do
return if method_defined?(method)
- if method.to_s =~ /\A[a-zA-Z_]\w*[!?]?\z/
+ if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(*args, &block)
scoping { @klass.#{method}(*args, &block) }
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 8a87015e44..0749bb30b5 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -4,6 +4,7 @@ require "active_record/relation/where_clause"
require "active_record/relation/where_clause_factory"
require 'active_model/forbidden_attributes_protection'
require 'active_support/core_ext/string/filters'
+require 'active_support/core_ext/regexp'
module ActiveRecord
module QueryMethods
@@ -1135,10 +1136,10 @@ module ActiveRecord
end
def does_not_support_reverse?(order)
- #uses sql function with multiple arguments
- order =~ /\([^()]*,[^()]*\)/ ||
- # uses "nulls first" like construction
- order =~ /nulls (first|last)\Z/i
+ # Uses SQL function with multiple arguments.
+ /\([^()]*,[^()]*\)/.match?(order) ||
+ # Uses "nulls first" like construction.
+ /nulls (first|last)\Z/i.match?(order)
end
def build_order(arel)
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index a9e1fd0dad..f007e9e733 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/regexp'
+
module ActiveRecord
module Sanitization
extend ActiveSupport::Concern
@@ -153,7 +155,7 @@ module ActiveRecord
# # => "name='foo''bar' and group_id='4'"
def sanitize_sql_array(ary)
statement, *values = ary
- if values.first.is_a?(Hash) && statement =~ /:\w+/
+ if values.first.is_a?(Hash) && /:\w+/.match?(statement)
replace_named_bind_variables(statement, values.first)
elsif statement.include?('?')
replace_bind_variables(statement, values)
diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
index b1a0ad0115..8574807fd2 100644
--- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
@@ -90,7 +90,7 @@ module ActiveRecord
end
def error_class
- if configuration['adapter'] =~ /jdbc/
+ if configuration['adapter'].include?('jdbc')
require 'active_record/railties/jdbcmysql_error'
ArJdbcMySQL::Error
elsif defined?(Mysql2)
diff --git a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
index 4e5872b585..de03550ec2 100644
--- a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
+++ b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
@@ -1,4 +1,5 @@
require 'rails/generators/active_record'
+require 'active_support/core_ext/regexp'
module ActiveRecord
module Generators # :nodoc:
@@ -60,7 +61,7 @@ module ActiveRecord
# A migration file name can only contain underscores (_), lowercase characters,
# and numbers 0-9. Any other file name will raise an IllegalMigrationNameError.
def validate_file_name!
- unless file_name =~ /^[_a-z0-9]+$/
+ unless /^[_a-z0-9]+$/.match?(file_name)
raise IllegalMigrationNameError.new(file_name)
end
end
diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb
index b3fe759ad9..a2158e4f3b 100644
--- a/activerecord/test/cases/associations/inner_join_association_test.rb
+++ b/activerecord/test/cases/associations/inner_join_association_test.rb
@@ -86,7 +86,7 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase
end
def test_calculate_honors_implicit_inner_joins_and_distinct_and_conditions
- real_count = Author.all.to_a.select {|a| a.posts.any? {|p| p.title =~ /^Welcome/} }.length
+ real_count = Author.all.to_a.select {|a| a.posts.any? {|p| p.title.start_with?('Welcome')} }.length
authors_with_welcoming_post_titles = Author.all.merge!(joins: :posts, where: "posts.title like 'Welcome%'").distinct.calculate(:count, 'authors.id')
assert_equal real_count, authors_with_welcoming_post_titles, "inner join and conditions should have only returned authors posting titles starting with 'Welcome'"
end
diff --git a/activerecord/test/cases/associations/left_outer_join_association_test.rb b/activerecord/test/cases/associations/left_outer_join_association_test.rb
index eee135cfb8..e3b257efb2 100644
--- a/activerecord/test/cases/associations/left_outer_join_association_test.rb
+++ b/activerecord/test/cases/associations/left_outer_join_association_test.rb
@@ -5,6 +5,7 @@ require 'models/author'
require 'models/essay'
require 'models/categorization'
require 'models/person'
+require 'active_support/core_ext/regexp'
class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
fixtures :authors, :essays, :posts, :comments, :categorizations, :people
@@ -20,7 +21,7 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
Person.left_outer_joins(:agents => {:agents => :agents})
.left_outer_joins(:agents => {:agents => {:primary_contact => :agents}}).to_a
end
- assert queries.any? { |sql| /agents_people_4/i =~ sql }
+ assert queries.any? { |sql| /agents_people_4/i.match?(sql) }
end
end
@@ -36,12 +37,12 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
def test_construct_finder_sql_ignores_empty_left_outer_joins_hash
queries = capture_sql { Author.left_outer_joins({}) }
- assert queries.none? { |sql| /LEFT OUTER JOIN/i =~ sql }
+ assert queries.none? { |sql| /LEFT OUTER JOIN/i.match?(sql) }
end
def test_construct_finder_sql_ignores_empty_left_outer_joins_array
queries = capture_sql { Author.left_outer_joins([]) }
- assert queries.none? { |sql| /LEFT OUTER JOIN/i =~ sql }
+ assert queries.none? { |sql| /LEFT OUTER JOIN/i.match?(sql) }
end
def test_left_outer_joins_forbids_to_use_string_as_argument
@@ -50,8 +51,8 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
def test_join_conditions_added_to_join_clause
queries = capture_sql { Author.left_outer_joins(:essays).to_a }
- assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|\:a1)/i =~ sql }
- assert queries.none? { |sql| /WHERE/i =~ sql }
+ assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|\:a1)/i.match?(sql) }
+ assert queries.none? { |sql| /WHERE/i.match?(sql) }
end
def test_find_with_sti_join
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 04126e87e4..9d66c9964c 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -27,34 +27,34 @@ class AttributeMethodsTest < ActiveRecord::TestCase
ActiveRecord::Base.send(:attribute_method_matchers).concat(@old_matchers)
end
- def test_attribute_for_inspect_string
+ test 'attribute_for_inspect with a string' do
t = topics(:first)
t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
assert_equal '"The First Topic Now Has A Title With\nNewlines And ..."', t.attribute_for_inspect(:title)
end
- def test_attribute_for_inspect_date
+ test 'attribute_for_inspect with a date' do
t = topics(:first)
assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
end
- def test_attribute_for_inspect_array
+ test 'attribute_for_inspect with an array' do
t = topics(:first)
t.content = [Object.new]
assert_match %r(\[#<Object:0x[0-9a-f]+>\]), t.attribute_for_inspect(:content)
end
- def test_attribute_for_inspect_long_array
+ test 'attribute_for_inspect with a long array' do
t = topics(:first)
t.content = (1..11).to_a
assert_equal "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", t.attribute_for_inspect(:content)
end
- def test_attribute_present
+ test 'attribute_present' do
t = Topic.new
t.title = "hello there!"
t.written_on = Time.now
@@ -65,7 +65,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert !t.attribute_present?("author_name")
end
- def test_attribute_present_with_booleans
+ test 'attribute_present with booleans' do
b1 = Boolean.new
b1.value = false
assert b1.attribute_present?(:value)
@@ -83,44 +83,44 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert Boolean.find(b4.id).attribute_present?(:value)
end
- def test_caching_nil_primary_key
+ test 'caching a nil primary key' do
klass = Class.new(Minimalistic)
assert_called(klass, :reset_primary_key, returns: nil) do
2.times { klass.primary_key }
end
end
- def test_attribute_keys_on_new_instance
+ test 'attribute keys on a new instance' do
t = Topic.new
assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
assert_raise(NoMethodError) { t.title2 }
end
- def test_boolean_attributes
+ test 'boolean attributes' do
assert !Topic.find(1).approved?
assert Topic.find(2).approved?
end
- def test_set_attributes
+ test 'set attributes' do
topic = Topic.find(1)
- topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
+ topic.attributes = { title: 'Budget', author_name: 'Jason' }
topic.save
- assert_equal("Budget", topic.title)
- assert_equal("Jason", topic.author_name)
+ assert_equal('Budget', topic.title)
+ assert_equal('Jason', topic.author_name)
assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
end
- def test_set_attributes_without_hash
+ test 'set attributes without a hash' do
topic = Topic.new
assert_raise(ArgumentError) { topic.attributes = '' }
end
- def test_integers_as_nil
- test = AutoId.create('value' => '')
+ test 'integers as nil' do
+ test = AutoId.create(value: '')
assert_nil AutoId.find(test.id).value
end
- def test_set_attributes_with_block
+ test 'set attributes with a block' do
topic = Topic.new do |t|
t.title = "Budget"
t.author_name = "Jason"
@@ -130,7 +130,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal("Jason", topic.author_name)
end
- def test_respond_to?
+ test 'respond_to?' do
topic = Topic.find(1)
assert_respond_to topic, "title"
assert_respond_to topic, "title?"
@@ -144,7 +144,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert !topic.respond_to?(:nothingness)
end
- def test_respond_to_with_custom_primary_key
+ test 'respond_to? with a custom primary key' do
keyboard = Keyboard.create
assert_not_nil keyboard.key_number
assert_equal keyboard.key_number, keyboard.id
@@ -152,7 +152,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert keyboard.respond_to?('id')
end
- def test_id_before_type_cast_with_custom_primary_key
+ test 'id_before_type_cast with a custom primary key' do
keyboard = Keyboard.create
keyboard.key_number = '10'
assert_equal '10', keyboard.id_before_type_cast
@@ -161,8 +161,8 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal '10', keyboard.read_attribute_before_type_cast(:key_number)
end
- # Syck calls respond_to? before actually calling initialize
- def test_respond_to_with_allocated_object
+ # Syck calls respond_to? before actually calling initialize.
+ test 'respond_to? with an allocated object' do
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'topics'
end
@@ -174,31 +174,32 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_respond_to topic, :title
end
- # IRB inspects the return value of "MyModel.allocate".
- def test_allocated_object_can_be_inspected
+ # IRB inspects the return value of MyModel.allocate.
+ test 'allocated objects can be inspected' do
topic = Topic.allocate
assert_equal "#<Topic not initialized>", topic.inspect
end
- def test_array_content
+ test 'array content' do
+ content = %w( one two three )
topic = Topic.new
- topic.content = %w( one two three )
+ topic.content = content
topic.save
- assert_equal(%w( one two three ), Topic.find(topic.id).content)
+ assert_equal content, Topic.find(topic.id).content
end
- def test_read_attributes_before_type_cast
- category = Category.new({:name=>"Test category", :type => nil})
- category_attrs = {"name"=>"Test category", "id" => nil, "type" => nil, "categorizations_count" => nil}
- assert_equal category_attrs , category.attributes_before_type_cast
+ test 'read attributes_before_type_cast' do
+ category = Category.new(name: 'Test category', type: nil)
+ category_attrs = { 'name' => 'Test category', 'id' => nil, 'type' => nil, 'categorizations_count' => nil }
+ assert_equal category_attrs, category.attributes_before_type_cast
end
if current_adapter?(:Mysql2Adapter)
- def test_read_attributes_before_type_cast_on_boolean
+ test 'read attributes_before_type_cast on a boolean' do
bool = Boolean.create!({ "value" => false })
- if RUBY_PLATFORM =~ /java/
- # JRuby will return the value before typecast as string
+ if RUBY_PLATFORM.include?('java')
+ # JRuby will return the value before typecast as string.
assert_equal "0", bool.reload.attributes_before_type_cast["value"]
else
assert_equal 0, bool.reload.attributes_before_type_cast["value"]
@@ -206,7 +207,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_read_attributes_before_type_cast_on_datetime
+ test 'read attributes_before_type_cast on a datetime' do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
@@ -221,7 +222,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_read_attributes_after_type_cast_on_datetime
+ test 'read attributes_after_type_cast on a date' do
tz = "Pacific Time (US & Canada)"
in_time_zone tz do
@@ -242,7 +243,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_hash_content
+ test 'hash content' do
topic = Topic.new
topic.content = { "one" => 1, "two" => 2 }
topic.save
@@ -256,7 +257,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal 3, Topic.find(topic.id).content["three"]
end
- def test_update_array_content
+ test 'update array content' do
topic = Topic.new
topic.content = %w( one two three )
@@ -270,14 +271,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal(%w( one two three four five ), topic.content)
end
- def test_case_sensitive_attributes_hash
- # DB2 is not case-sensitive
+ test 'case-sensitive attributes hash' do
+ # DB2 is not case-sensitive.
return true if current_adapter?(:DB2Adapter)
assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes
end
- def test_attributes_without_primary_key
+ test 'attributes without primary key' do
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'developers_projects'
end
@@ -286,9 +287,9 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_not klass.new.has_attribute?('id')
end
- def test_hashes_not_mangled
- new_topic = { :title => "New Topic" }
- new_topic_values = { :title => "AnotherTopic" }
+ test 'hashes are not mangled' do
+ new_topic = { title: 'New Topic' }
+ new_topic_values = { title: 'AnotherTopic' }
topic = Topic.new(new_topic)
assert_equal new_topic[:title], topic.title
@@ -297,13 +298,13 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal new_topic_values[:title], topic.title
end
- def test_create_through_factory
- topic = Topic.create("title" => "New Topic")
+ test 'create through factory' do
+ topic = Topic.create(title: 'New Topic')
topicReloaded = Topic.find(topic.id)
assert_equal(topic, topicReloaded)
end
- def test_write_attribute
+ test 'write_attribute' do
topic = Topic.new
topic.send(:write_attribute, :title, "Still another topic")
assert_equal "Still another topic", topic.title
@@ -318,7 +319,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "Still another topic: part 4", topic.title
end
- def test_read_attribute
+ test 'read_attribute' do
topic = Topic.new
topic.title = "Don't change the topic"
assert_equal "Don't change the topic", topic.read_attribute("title")
@@ -328,7 +329,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "Don't change the topic", topic[:title]
end
- def test_read_attribute_raises_missing_attribute_error_when_not_exists
+ test 'read_attribute raises ActiveModel::MissingAttributeError when the attribute does not exist' do
computer = Computer.select('id').first
assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
@@ -336,7 +337,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_nothing_raised { computer[:developer] = 'Hello!' }
end
- def test_read_attribute_when_false
+ test 'read_attribute when false' do
topic = topics(:first)
topic.approved = false
assert !topic.approved?, "approved should be false"
@@ -344,7 +345,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert !topic.approved?, "approved should be false"
end
- def test_read_attribute_when_true
+ test 'read_attribute when true' do
topic = topics(:first)
topic.approved = true
assert topic.approved?, "approved should be true"
@@ -352,7 +353,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert topic.approved?, "approved should be true"
end
- def test_read_write_boolean_attribute
+ test 'boolean attributes writing and reading' do
topic = Topic.new
topic.approved = "false"
assert !topic.approved?, "approved should be false"
@@ -367,7 +368,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert topic.approved?, "approved should be true"
end
- def test_overridden_write_attribute
+ test 'overridden write_attribute' do
topic = Topic.new
def topic.write_attribute(attr_name, value)
super(attr_name, value.downcase)
@@ -386,7 +387,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "yet another topic: part 4", topic.title
end
- def test_overridden_read_attribute
+ test 'overridden read_attribute' do
topic = Topic.new
topic.title = "Stop changing the topic"
def topic.read_attribute(attr_name)
@@ -400,40 +401,40 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "STOP CHANGING THE TOPIC", topic[:title]
end
- def test_read_overridden_attribute
- topic = Topic.new(:title => 'a')
+ test 'read overridden attribute' do
+ topic = Topic.new(title: 'a')
def topic.title() 'b' end
assert_equal 'a', topic[:title]
end
- def test_query_attribute_string
+ test 'string attribute predicate' do
[nil, "", " "].each do |value|
- assert_equal false, Topic.new(:author_name => value).author_name?
+ assert_equal false, Topic.new(author_name: value).author_name?
end
- assert_equal true, Topic.new(:author_name => "Name").author_name?
+ assert_equal true, Topic.new(author_name: 'Name').author_name?
end
- def test_query_attribute_number
- [nil, 0, "0"].each do |value|
- assert_equal false, Developer.new(:salary => value).salary?
+ test 'number attribute predicate' do
+ [nil, 0, '0'].each do |value|
+ assert_equal false, Developer.new(salary: value).salary?
end
- assert_equal true, Developer.new(:salary => 1).salary?
- assert_equal true, Developer.new(:salary => "1").salary?
+ assert_equal true, Developer.new(salary: 1).salary?
+ assert_equal true, Developer.new(salary: '1').salary?
end
- def test_query_attribute_boolean
+ test 'boolean attribute predicate' do
[nil, "", false, "false", "f", 0].each do |value|
- assert_equal false, Topic.new(:approved => value).approved?
+ assert_equal false, Topic.new(approved: value).approved?
end
[true, "true", "1", 1].each do |value|
- assert_equal true, Topic.new(:approved => value).approved?
+ assert_equal true, Topic.new(approved: value).approved?
end
end
- def test_query_attribute_with_custom_fields
+ test 'custom field attribute predicate' do
object = Company.find_by_sql(<<-SQL).first
SELECT c1.*, c2.type as string_value, c2.rating as int_value
FROM companies c1, companies c2
@@ -454,23 +455,23 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert !object.int_value?
end
- def test_non_attribute_access_and_assignment
+ test 'non-attribute read and write' do
topic = Topic.new
assert !topic.respond_to?("mumbo")
assert_raise(NoMethodError) { topic.mumbo }
assert_raise(NoMethodError) { topic.mumbo = 5 }
end
- def test_undeclared_attribute_method_does_not_affect_respond_to_and_method_missing
- topic = @target.new(:title => 'Budget')
+ test 'undeclared attribute method does not affect respond_to? and method_missing' do
+ topic = @target.new(title: 'Budget')
assert topic.respond_to?('title')
assert_equal 'Budget', topic.title
assert !topic.respond_to?('title_hello_world')
assert_raise(NoMethodError) { topic.title_hello_world }
end
- def test_declared_prefixed_attribute_method_affects_respond_to_and_method_missing
- topic = @target.new(:title => 'Budget')
+ test 'declared prefixed attribute method affects respond_to? and method_missing' do
+ topic = @target.new(title: 'Budget')
%w(default_ title_).each do |prefix|
@target.class_eval "def #{prefix}attribute(*args) args end"
@target.attribute_method_prefix prefix
@@ -483,11 +484,11 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_declared_suffixed_attribute_method_affects_respond_to_and_method_missing
+ test 'declared suffixed attribute method affects respond_to? and method_missing' do
%w(_default _title_default _it! _candidate= able?).each do |suffix|
@target.class_eval "def attribute#{suffix}(*args) args end"
@target.attribute_method_suffix suffix
- topic = @target.new(:title => 'Budget')
+ topic = @target.new(title: 'Budget')
meth = "title#{suffix}"
assert topic.respond_to?(meth)
@@ -497,11 +498,11 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_declared_affixed_attribute_method_affects_respond_to_and_method_missing
+ test 'declared affixed attribute method affects respond_to? and method_missing' do
[['mark_', '_for_update'], ['reset_', '!'], ['default_', '_value?']].each do |prefix, suffix|
@target.class_eval "def #{prefix}attribute#{suffix}(*args) args end"
- @target.attribute_method_affix({ :prefix => prefix, :suffix => suffix })
- topic = @target.new(:title => 'Budget')
+ @target.attribute_method_affix(prefix: prefix, suffix: suffix)
+ topic = @target.new(title: 'Budget')
meth = "#{prefix}title#{suffix}"
assert topic.respond_to?(meth)
@@ -511,38 +512,38 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_should_unserialize_attributes_for_frozen_records
- myobj = {:value1 => :value2}
- topic = Topic.create("content" => myobj)
+ test 'should unserialize attributes for frozen records' do
+ myobj = { value1: :value2 }
+ topic = Topic.create(content: myobj)
topic.freeze
assert_equal myobj, topic.content
end
- def test_typecast_attribute_from_select_to_false
- Topic.create(:title => 'Budget')
- # Oracle does not support boolean expressions in SELECT
+ test 'typecast attribute from select to false' do
+ Topic.create(title: 'Budget')
+ # Oracle does not support boolean expressions in SELECT.
if current_adapter?(:OracleAdapter, :FbAdapter)
- topic = Topic.all.merge!(:select => "topics.*, 0 as is_test").first
+ topic = Topic.all.merge!(select: 'topics.*, 0 as is_test').first
else
- topic = Topic.all.merge!(:select => "topics.*, 1=2 as is_test").first
+ topic = Topic.all.merge!(select: 'topics.*, 1=2 as is_test').first
end
assert !topic.is_test?
end
- def test_typecast_attribute_from_select_to_true
- Topic.create(:title => 'Budget')
- # Oracle does not support boolean expressions in SELECT
+ test 'typecast attribute from select to true' do
+ Topic.create(title: 'Budget')
+ # Oracle does not support boolean expressions in SELECT.
if current_adapter?(:OracleAdapter, :FbAdapter)
- topic = Topic.all.merge!(:select => "topics.*, 1 as is_test").first
+ topic = Topic.all.merge!(select: 'topics.*, 1 as is_test').first
else
- topic = Topic.all.merge!(:select => "topics.*, 2=2 as is_test").first
+ topic = Topic.all.merge!(select: 'topics.*, 2=2 as is_test').first
end
assert topic.is_test?
end
- def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
+ test 'raises ActiveRecord::DangerousAttributeError when defining an AR method in a model' do
%w(save create_or_update).each do |method|
- klass = Class.new ActiveRecord::Base
+ klass = Class.new(ActiveRecord::Base)
klass.class_eval "def #{method}() 'defined #{method}' end"
assert_raise ActiveRecord::DangerousAttributeError do
klass.instance_method_already_implemented?(method)
@@ -550,7 +551,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_converted_values_are_returned_after_assignment
+ test 'converted values are returned after assignment' do
developer = Developer.new(name: 1337, salary: "50000")
assert_equal "50000", developer.salary_before_type_cast
@@ -565,7 +566,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "1337", developer.name
end
- def test_write_nil_to_time_attributes
+ test 'write nil to time attribute' do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.written_on = nil
@@ -573,7 +574,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_write_time_to_date_attributes
+ test 'write time to date attribute' do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.last_read = Time.utc(2010, 1, 1, 10)
@@ -581,7 +582,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_time_attributes_are_retrieved_in_current_time_zone
+ test 'time attributes are retrieved in the current time zone' do
in_time_zone "Pacific Time (US & Canada)" do
utc_time = Time.utc(2008, 1, 1)
record = @target.new
@@ -593,7 +594,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_attribute_to_utc
+ test 'setting a time zone-aware attribute to UTC' do
in_time_zone "Pacific Time (US & Canada)" do
utc_time = Time.utc(2008, 1, 1)
record = @target.new
@@ -604,7 +605,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_attribute_in_other_time_zone
+ test 'setting time zone-aware attribute in other time zone' do
utc_time = Time.utc(2008, 1, 1)
cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
in_time_zone "Pacific Time (US & Canada)" do
@@ -616,18 +617,18 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_read_attribute
+ test 'setting time zone-aware read attribute' do
utc_time = Time.utc(2008, 1, 1)
cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
in_time_zone "Pacific Time (US & Canada)" do
- record = @target.create(:written_on => cst_time).reload
+ record = @target.create(written_on: cst_time).reload
assert_equal utc_time, record[:written_on]
assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record[:written_on].time_zone
assert_equal Time.utc(2007, 12, 31, 16), record[:written_on].time
end
end
- def test_setting_time_zone_aware_attribute_with_string
+ test 'setting time zone-aware attribute with a string' do
utc_time = Time.utc(2008, 1, 1)
(-11..13).each do |timezone_offset|
time_string = utc_time.in_time_zone(timezone_offset).to_s
@@ -641,9 +642,9 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_time_zone_aware_attribute_saved
+ test 'time zone-aware attribute saved' do
in_time_zone 1 do
- record = @target.create(:written_on => '2012-02-20 10:00')
+ record = @target.create(written_on: '2012-02-20 10:00')
record.written_on = '2012-02-20 09:00'
record.save
@@ -651,7 +652,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
+ test 'setting a time zone-aware attribute to a blank string returns nil' do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.written_on = ' '
@@ -660,7 +661,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
+ test 'setting a time zone-aware attribute interprets time zone-unaware string in time zone' do
time_string = 'Tue Jan 01 00:00:00 2008'
(-11..13).each do |timezone_offset|
in_time_zone timezone_offset do
@@ -673,7 +674,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_datetime_in_current_time_zone
+ test 'setting a time zone-aware datetime in the current time zone' do
utc_time = Time.utc(2008, 1, 1)
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
@@ -684,7 +685,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_yaml_dumping_record_with_time_zone_aware_attribute
+ test 'YAML dumping a record with time zone-aware attribute' do
in_time_zone "Pacific Time (US & Canada)" do
record = Topic.new(id: 1)
record.written_on = "Jan 01 00:00:00 2014"
@@ -692,7 +693,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_time_in_current_time_zone
+ test 'setting a time zone-aware time in the current time zone' do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
time_string = "10:00:00"
@@ -707,7 +708,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_setting_time_zone_aware_time_with_dst
+ test 'setting a time zone-aware time with DST' do
in_time_zone "Pacific Time (US & Canada)" do
current_time = Time.zone.local(2014, 06, 15, 10)
record = @target.new(bonus_time: current_time)
@@ -721,7 +722,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_removing_time_zone_aware_types
+ test 'removing time zone-aware types' do
with_time_zone_aware_types(:datetime) do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new(bonus_time: "10:00:00")
@@ -733,14 +734,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_time_zone_aware_attributes_dont_recurse_infinitely_on_invalid_values
+ test 'time zone-aware attributes do not recurse infinitely on invalid values' do
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new(bonus_time: [])
assert_equal nil, record.bonus_time
end
end
- def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
+ test 'setting a time_zone_conversion_for_attributes should write the value on a class variable' do
Topic.skip_time_zone_conversion_for_attributes = [:field_a]
Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
@@ -748,44 +749,44 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
end
- def test_read_attributes_respect_access_control
- privatize("title")
+ test 'attribute readers respect access control' do
+ privatize('title')
- topic = @target.new(:title => "The pros and cons of programming naked.")
+ topic = @target.new(title: 'The pros and cons of programming naked.')
assert !topic.respond_to?(:title)
exception = assert_raise(NoMethodError) { topic.title }
- assert exception.message.include?("private method")
+ assert exception.message.include?('private method')
assert_equal "I'm private", topic.send(:title)
end
- def test_write_attributes_respect_access_control
- privatize("title=(value)")
+ test 'attribute writers respect access control' do
+ privatize('title=(value)')
topic = @target.new
assert !topic.respond_to?(:title=)
- exception = assert_raise(NoMethodError) { topic.title = "Pants"}
- assert exception.message.include?("private method")
- topic.send(:title=, "Very large pants")
+ exception = assert_raise(NoMethodError) { topic.title = 'Pants' }
+ assert exception.message.include?('private method')
+ topic.send(:title=, 'Very large pants')
end
- def test_question_attributes_respect_access_control
- privatize("title?")
+ test 'attribute predicates respect access control' do
+ privatize('title?')
- topic = @target.new(:title => "Isaac Newton's pants")
+ topic = @target.new(title: "Isaac Newton's pants")
assert !topic.respond_to?(:title?)
exception = assert_raise(NoMethodError) { topic.title? }
- assert exception.message.include?("private method")
+ assert exception.message.include?('private method')
assert topic.send(:title?)
end
- def test_bulk_update_respects_access_control
- privatize("title=(value)")
+ test 'bulk updates respect access control' do
+ privatize('title=(value)')
- assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
- assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(title: 'Rants about pants') }
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { title: 'Ants in pants' } }
end
- def test_bulk_update_raise_unknown_attribute_error
+ test 'bulk update raises ActiveRecord::UnknownAttributeError' do
error = assert_raises(ActiveRecord::UnknownAttributeError) {
Topic.new(hello: "world")
}
@@ -794,20 +795,20 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "unknown attribute 'hello' for Topic.", error.message
end
- def test_methods_override_in_multi_level_subclass
+ test 'method overrides in multi-level subclasses' do
klass = Class.new(Developer) do
def name
"dev:#{read_attribute(:name)}"
end
end
- 2.times { klass = Class.new klass }
+ 2.times { klass = Class.new(klass) }
dev = klass.new(name: 'arthurnn')
dev.save!
assert_equal 'dev:arthurnn', dev.reload.name
end
- def test_global_methods_are_overwritten
+ test 'global methods are overwritten' do
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'computers'
end
@@ -817,8 +818,10 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_nil computer.system
end
- def test_global_methods_are_overwritten_when_subclassing
- klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
+ test 'global methods are overwritten when subclassing' do
+ klass = Class.new(ActiveRecord::Base) do
+ self.abstract_class = true
+ end
subklass = Class.new(klass) do
self.table_name = 'computers'
@@ -830,7 +833,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_nil computer.system
end
- def test_instance_method_should_be_defined_on_the_base_class
+ test 'instance methods should be defined on the base class' do
subklass = Class.new(Topic)
Topic.define_attribute_methods
@@ -846,14 +849,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert subklass.method_defined?(:id), "subklass is missing id method"
end
- def test_read_attribute_with_nil_should_not_asplode
- assert_equal nil, Topic.new.read_attribute(nil)
+ test 'read_attribute with nil should not asplode' do
+ assert_nil Topic.new.read_attribute(nil)
end
# If B < A, and A defines an accessor for 'foo', we don't want to override
# that by defining a 'foo' method in the generated methods module for B.
# (That module will be inserted between the two, e.g. [B, <GeneratedAttributes>, A].)
- def test_inherited_custom_accessors
+ test 'inherited custom accessors' do
klass = new_topic_like_ar_class do
self.abstract_class = true
def title; "omg"; end
@@ -869,7 +872,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "lol", topic.author_name
end
- def test_inherited_custom_accessors_with_reserved_names
+ test 'inherited custom accessors with reserved names' do
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'computers'
self.abstract_class = true
@@ -887,7 +890,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal 99, computer.developer
end
- def test_on_the_fly_super_invokable_generated_attribute_methods_via_method_missing
+ test 'on_the_fly_super_invokable_generated_attribute_methods_via_method_missing' do
klass = new_topic_like_ar_class do
def title
super + '!'
@@ -898,7 +901,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal real_topic.title + '!', klass.find(real_topic.id).title
end
- def test_on_the_fly_super_invokable_generated_predicate_attribute_methods_via_method_missing
+ test 'on-the-fly super-invokable generated attribute predicates via method_missing' do
klass = new_topic_like_ar_class do
def title?
!super
@@ -909,7 +912,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal !real_topic.title?, klass.find(real_topic.id).title?
end
- def test_calling_super_when_parent_does_not_define_method_raises_error
+ test 'calling super when the parent does not define method raises NoMethodError' do
klass = new_topic_like_ar_class do
def some_method_that_is_not_on_super
super
@@ -921,38 +924,38 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
- def test_attribute_method?
+ test 'attribute_method?' do
assert @target.attribute_method?(:title)
assert @target.attribute_method?(:title=)
assert_not @target.attribute_method?(:wibble)
end
- def test_attribute_method_returns_false_if_table_does_not_exist
+ test 'attribute_method? returns false if the table does not exist' do
@target.table_name = 'wibble'
assert_not @target.attribute_method?(:title)
end
- def test_attribute_names_on_new_record
+ test 'attribute_names on a new record' do
model = @target.new
assert_equal @target.column_names, model.attribute_names
end
- def test_attribute_names_on_queried_record
+ test 'attribute_names on a queried record' do
model = @target.last!
assert_equal @target.column_names, model.attribute_names
end
- def test_attribute_names_with_custom_select
+ test 'attribute_names with a custom select' do
model = @target.select('id').last!
assert_equal ['id'], model.attribute_names
- # Sanity check, make sure other columns exist
+ # Sanity check, make sure other columns exist.
assert_not_equal ['id'], @target.column_names
end
- def test_came_from_user
+ test 'came_from_user?' do
model = @target.first
assert_not model.id_came_from_user?
@@ -960,7 +963,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert model.id_came_from_user?
end
- def test_accessed_fields
+ test 'accessed_fields' do
model = @target.first
assert_equal [], model.accessed_fields
diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb
index 7bcaa53aa2..604411da97 100644
--- a/activerecord/test/cases/attributes_test.rb
+++ b/activerecord/test/cases/attributes_test.rb
@@ -205,5 +205,49 @@ module ActiveRecord
assert_equal(:bar, child.new(foo: :bar).foo)
end
+
+ test "attributes not backed by database columns are not dirty when unchanged" do
+ refute OverloadedType.new.non_existent_decimal_changed?
+ end
+
+ test "attributes not backed by database columns are always initialized" do
+ OverloadedType.create!
+ model = OverloadedType.first
+
+ assert_nil model.non_existent_decimal
+ model.non_existent_decimal = "123"
+ assert_equal 123, model.non_existent_decimal
+ end
+
+ test "attributes not backed by database columns return the default on models loaded from database" do
+ child = Class.new(OverloadedType) do
+ attribute :non_existent_decimal, :decimal, default: 123
+ end
+ child.create!
+ model = child.first
+
+ assert_equal 123, model.non_existent_decimal
+ end
+
+ test "attributes not backed by database columns properly interact with mutation and dirty" do
+ child = Class.new(ActiveRecord::Base) do
+ self.table_name = "topics"
+ attribute :foo, :string, default: "lol"
+ end
+ child.create!
+ model = child.first
+
+ assert_equal "lol", model.foo
+
+ model.foo << "asdf"
+ assert_equal "lolasdf", model.foo
+ assert model.foo_changed?
+
+ model.reload
+ assert_equal "lol", model.foo
+
+ model.foo = "lol"
+ refute model.changed?
+ end
end
end
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index 4f70ae3a1d..8a722b4f22 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -31,7 +31,7 @@ class CallbackDeveloper < ActiveRecord::Base
end
ActiveRecord::Callbacks::CALLBACKS.each do |callback_method|
- next if callback_method.to_s =~ /^around_/
+ next if callback_method.to_s.start_with?('around_')
define_callback_method(callback_method)
ActiveSupport::Deprecation.silence { send(callback_method, callback_string(callback_method)) }
send(callback_method, callback_proc(callback_method))
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index f9794518c7..3c58b6ad09 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -604,7 +604,7 @@ class DirtyTest < ActiveRecord::TestCase
jon = Person.create! first_name: 'Jon'
end
- assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql =~ /followers_count/ }
+ assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql.include?('followers_count') }
jon.reload
assert_equal 'Jon', jon.first_name
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index dcd09b6973..6679f9415b 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -5,6 +5,7 @@ require 'models/developer'
require 'models/computer'
require 'models/vehicle'
require 'models/cat'
+require 'active_support/core_ext/regexp'
class DefaultScopingTest < ActiveRecord::TestCase
fixtures :developers, :posts, :comments
@@ -201,7 +202,7 @@ class DefaultScopingTest < ActiveRecord::TestCase
def test_order_to_unscope_reordering
scope = DeveloperOrderedBySalary.order('salary DESC, name ASC').reverse_order.unscope(:order)
- assert !(scope.to_sql =~ /order/i)
+ assert !/order/i.match?(scope.to_sql)
end
def test_unscope_reverse_order
diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb
index c8adc21bbc..fcb6552e5b 100644
--- a/activerecord/test/cases/test_case.rb
+++ b/activerecord/test/cases/test_case.rb
@@ -1,5 +1,6 @@
require 'active_support/test_case'
require 'active_support/testing/stream'
+require 'active_support/core_ext/regexp'
module ActiveRecord
# = Active Record Test Case
@@ -115,7 +116,7 @@ module ActiveRecord
return if 'CACHE' == values[:name]
self.class.log_all << sql
- self.class.log << sql unless ignore =~ sql
+ self.class.log << sql unless ignore.match?(sql)
end
end
diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb
index 24713f722a..030ad73621 100644
--- a/activerecord/test/schema/postgresql_specific_schema.rb
+++ b/activerecord/test/schema/postgresql_specific_schema.rb
@@ -88,7 +88,7 @@ _SQL
FOR EACH ROW EXECUTE PROCEDURE partitioned_insert_trigger();
_SQL
rescue ActiveRecord::StatementInvalid => e
- if e.message =~ /language "plpgsql" does not exist/
+ if e.message.include?('language "plpgsql" does not exist')
execute "CREATE LANGUAGE 'plpgsql';"
retry
else
diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md
index ad1f20e645..cc84ecb216 100644
--- a/guides/source/caching_with_rails.md
+++ b/guides/source/caching_with_rails.md
@@ -270,7 +270,7 @@ simply be explicit in a comment, like:
Sometimes you need to cache a particular value or query result instead of caching view fragments. Rails' caching mechanism works great for storing __any__ kind of information.
-The most efficient way to implement low-level caching is using the `Rails.cache.fetch` method. This method does both reading and writing to the cache. When passed only a single argument, the key is fetched and value from the cache is returned. If a block is passed, the result of the block will be cached to the given key and the result is returned.
+The most efficient way to implement low-level caching is using the `Rails.cache.fetch` method. This method does both reading and writing to the cache. When passed only a single argument, the key is fetched and value from the cache is returned. If a block is passed, that block will be executed in the event of a cache miss. The return value of the block will be written to the cache under the given cache key, and that return value will be returned. In case of cache hit, the cached value will be returned without executing the block.
Consider the following example. An application has a `Product` model with an instance method that looks up the product’s price on a competing website. The data returned by this method would be perfect for low-level caching: