aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock26
-rw-r--r--actioncable/README.md2
-rw-r--r--actioncable/lib/action_cable/connection/stream.rb1
-rw-r--r--actioncable/lib/action_cable/connection/stream_event_loop.rb1
-rw-r--r--actioncable/test/client_test.rb7
-rw-r--r--actioncable/test/connection/client_socket_test.rb12
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb2
-rw-r--r--actionpack/test/controller/integration_test.rb8
-rw-r--r--actionpack/test/controller/live_stream_test.rb4
-rw-r--r--actionview/lib/action_view/digestor.rb6
-rw-r--r--actionview/lib/action_view/railtie.rb2
-rw-r--r--activejob/CHANGELOG.md4
-rw-r--r--activejob/lib/active_job/arguments.rb4
-rw-r--r--activemodel/lib/active_model/type/float.rb9
-rw-r--r--activerecord/lib/active_record/log_subscriber.rb3
-rw-r--r--activerecord/lib/active_record/query_cache.rb10
-rw-r--r--activerecord/lib/active_record/reflection.rb4
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb8
-rw-r--r--activerecord/test/cases/adapters/postgresql/transaction_test.rb44
-rw-r--r--activerecord/test/cases/migration/column_attributes_test.rb6
-rw-r--r--activerecord/test/cases/query_cache_test.rb2
-rw-r--r--activerecord/test/cases/relations_test.rb2
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb14
-rw-r--r--activerecord/test/cases/type/date_time_test.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/conversions.rb2
-rw-r--r--activesupport/lib/active_support/deprecation/instance_delegator.rb13
-rw-r--r--activesupport/lib/active_support/execution_wrapper.rb33
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb2
-rw-r--r--activesupport/lib/active_support/xml_mini.rb4
-rw-r--r--activesupport/test/core_ext/array/grouping_test.rb4
-rw-r--r--activesupport/test/executor_test.rb55
-rw-r--r--guides/source/action_cable_overview.md2
34 files changed, 211 insertions, 94 deletions
diff --git a/.travis.yml b/.travis.yml
index 585791f757..88dd6b7b5d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,7 +35,7 @@ env:
matrix:
- "GEM=railties"
- "GEM=ap"
- - "GEM=ac TESTOPTS=-vs26"
+ - "GEM=ac"
- "GEM=ac:integration"
- "GEM=am,amo,as,av,aj"
- "GEM=as PRESERVE_TIMEZONES=1"
@@ -66,7 +66,6 @@ matrix:
allow_failures:
- rvm: ruby-head
- rvm: jruby-9.0.5.0
- - env: "GEM=ac:integration"
fast_finish: true
notifications:
diff --git a/Gemfile b/Gemfile
index e4d625d47c..53044252a0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -36,7 +36,7 @@ gem "sass", github: "sass/sass", branch: "stable", require: false
gem "rb-inotify", github: "matthewd/rb-inotify", branch: "close-handling", require: false
group :doc do
- gem "sdoc", "~> 0.4.0"
+ gem "sdoc", "1.0.0.beta2"
gem "redcarpet", "~> 3.2.3", platforms: :ruby
gem "w3c_validators"
gem "kindlerb", "0.1.1"
@@ -72,7 +72,7 @@ group :cable do
gem "hiredis", require: false
gem "redis", require: false
- gem "websocket-client-simple", require: false
+ gem "websocket-client-simple", github: "matthewd/websocket-client-simple", branch: "close-race", require: false
gem "blade", require: false, platforms: [:ruby]
gem "blade-sauce_labs_plugin", require: false, platforms: [:ruby]
diff --git a/Gemfile.lock b/Gemfile.lock
index 14635a8cb2..d4059c607d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -30,6 +30,15 @@ GIT
ffi (>= 0.5.0)
GIT
+ remote: https://github.com/matthewd/websocket-client-simple.git
+ revision: e161305f1a466b9398d86df3b1731b03362da91b
+ branch: close-race
+ specs:
+ websocket-client-simple (0.3.0)
+ event_emitter
+ websocket
+
+GIT
remote: https://github.com/resque/resque.git
revision: 20d885065ac19e7f7d7a982f4ed1296083db0300
specs:
@@ -201,7 +210,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- json (1.8.3)
+ json (2.0.2)
kindlerb (0.1.1)
mustache
nokogiri
@@ -267,8 +276,7 @@ GEM
loofah (~> 2.0)
rake (11.3.0)
rb-fsevent (0.9.7)
- rdoc (4.2.2)
- json (~> 1.4)
+ rdoc (5.0.0.beta2)
redcarpet (3.2.3)
redis (3.3.1)
redis-namespace (1.5.2)
@@ -287,9 +295,8 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
- sdoc (0.4.1)
- json (~> 1.7, >= 1.7.7)
- rdoc (~> 4.0)
+ sdoc (1.0.0.beta2)
+ rdoc (= 5.0.0.beta2)
selenium-webdriver (2.53.4)
childprocess (~> 0.5)
rubyzip (~> 1.0)
@@ -350,9 +357,6 @@ GEM
nokogiri
wdm (0.1.1)
websocket (1.2.3)
- websocket-client-simple (0.3.0)
- event_emitter
- websocket
websocket-driver (0.6.4)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
@@ -402,7 +406,7 @@ DEPENDENCIES
resque-scheduler
sass!
sass-rails
- sdoc (~> 0.4.0)
+ sdoc (= 1.0.0.beta2)
sequel
sidekiq
sneakers
@@ -414,7 +418,7 @@ DEPENDENCIES
uglifier (>= 1.3.0)
w3c_validators
wdm (>= 0.1.0)
- websocket-client-simple
+ websocket-client-simple!
BUNDLED WITH
1.13.2
diff --git a/actioncable/README.md b/actioncable/README.md
index 28e2602cbf..a0b7412dd4 100644
--- a/actioncable/README.md
+++ b/actioncable/README.md
@@ -167,7 +167,7 @@ App.cable.subscriptions.create "AppearanceChannel",
buttonSelector = "[data-behavior~=appear_away]"
install: ->
- $(document).on "page:change.appearance", =>
+ $(document).on "turbolinks:load.appearance", =>
@appear()
$(document).on "click.appearance", buttonSelector, =>
diff --git a/actioncable/lib/action_cable/connection/stream.rb b/actioncable/lib/action_cable/connection/stream.rb
index d66e1b4e41..e620b93845 100644
--- a/actioncable/lib/action_cable/connection/stream.rb
+++ b/actioncable/lib/action_cable/connection/stream.rb
@@ -106,7 +106,6 @@ module ActionCable
def clean_rack_hijack
return unless @rack_hijack_io
@event_loop.detach(@rack_hijack_io, self)
- @rack_hijack_io.close
@rack_hijack_io = nil
end
end
diff --git a/actioncable/lib/action_cable/connection/stream_event_loop.rb b/actioncable/lib/action_cable/connection/stream_event_loop.rb
index eec24638b6..2d1af0ff9f 100644
--- a/actioncable/lib/action_cable/connection/stream_event_loop.rb
+++ b/actioncable/lib/action_cable/connection/stream_event_loop.rb
@@ -36,6 +36,7 @@ module ActionCable
@todo << lambda do
@nio.deregister io
@map.delete io
+ io.close
end
wakeup
end
diff --git a/actioncable/test/client_test.rb b/actioncable/test/client_test.rb
index f6d4ab3202..db10a7ad16 100644
--- a/actioncable/test/client_test.rb
+++ b/actioncable/test/client_test.rb
@@ -21,13 +21,6 @@ WebSocket::Frame::Data.prepend Module.new {
super
end
}
-
-WebSocket::Client::Simple::Client.prepend Module.new {
- def initialize(*)
- @socket = nil
- super
- end
-}
#
####
diff --git a/actioncable/test/connection/client_socket_test.rb b/actioncable/test/connection/client_socket_test.rb
index dff7fefbfb..bc3ff6a3d7 100644
--- a/actioncable/test/connection/client_socket_test.rb
+++ b/actioncable/test/connection/client_socket_test.rb
@@ -51,10 +51,12 @@ class ActionCable::Connection::ClientSocketTest < ActionCable::TestCase
connection = open_connection
client = connection.websocket.send(:websocket)
+ event = Concurrent::Event.new
client.instance_variable_get("@stream")
.instance_variable_get("@rack_hijack_io")
- .expects(:close)
+ .define_singleton_method(:close) { event.set }
connection.close
+ event.wait
end
end
@@ -63,7 +65,13 @@ class ActionCable::Connection::ClientSocketTest < ActionCable::TestCase
env = Rack::MockRequest.env_for "/test",
"HTTP_CONNECTION" => "upgrade", "HTTP_UPGRADE" => "websocket",
"HTTP_HOST" => "localhost", "HTTP_ORIGIN" => "http://rubyonrails.com"
- env["rack.hijack"] = -> { env["rack.hijack_io"] = StringIO.new }
+ io = \
+ begin
+ Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0).first
+ rescue
+ StringIO.new
+ end
+ env["rack.hijack"] = -> { env["rack.hijack_io"] = io }
Connection.new(@server, env).tap do |connection|
connection.process
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 720651fa1f..265459f79e 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -713,6 +713,8 @@ module ActionDispatch
class IntegrationTest < ActiveSupport::TestCase
include TestProcess
+ undef :assigns
+
module UrlOptions
extend ActiveSupport::Concern
def url_options
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index d3bc77d3ef..cf96b9b752 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -383,6 +383,14 @@ class IntegrationTestTest < ActiveSupport::TestCase
mixin.__send__(:remove_method, :method_missing)
end
end
+
+ def test_assigns_is_undefined_and_not_point_to_the_gem
+ e = assert_raises(NoMethodError) do
+ @test.assigns(:foo)
+ end
+
+ assert_match(/undefined method/, e.message)
+ end
end
# Tests that integration tests don't call Controller test methods for processing.
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 1361e95081..e76628b936 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -157,7 +157,9 @@ module ActionController
response.headers["Content-Type"] = "text/event-stream"
response.stream.write "before load"
sleep 0.01
- ::LoadMe
+ silence_warning do
+ ::LoadMe
+ end
response.stream.close
latch.count_down
diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb
index 2d6ad8f6d9..0658d8601d 100644
--- a/actionview/lib/action_view/digestor.rb
+++ b/actionview/lib/action_view/digestor.rb
@@ -6,6 +6,12 @@ module ActionView
class Digestor
@@digest_mutex = Mutex.new
+ module PerExecutionDigestCacheExpiry
+ def self.before(target)
+ ActionView::LookupContext::DetailsKey.clear
+ end
+ end
+
class << self
# Supported options:
#
diff --git a/actionview/lib/action_view/railtie.rb b/actionview/lib/action_view/railtie.rb
index dfb99f4ea9..42795ca2c7 100644
--- a/actionview/lib/action_view/railtie.rb
+++ b/actionview/lib/action_view/railtie.rb
@@ -40,7 +40,7 @@ module ActionView
initializer "action_view.per_request_digest_cache" do |app|
ActiveSupport.on_load(:action_view) do
if app.config.consider_all_requests_local
- app.executor.to_run { ActionView::LookupContext::DetailsKey.clear }
+ app.executor.to_run ActionView::Digestor::PerExecutionDigestCacheExpiry
end
end
end
diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md
index 9bf397af14..ef62b2136b 100644
--- a/activejob/CHANGELOG.md
+++ b/activejob/CHANGELOG.md
@@ -16,13 +16,13 @@
class RemoteServiceJob < ActiveJob::Base
retry_on CustomAppException # defaults to 3s wait, 5 attempts
retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
- retry_on ActiveRecord::StatementInvalid, wait: 5.seconds, attempts: 3
+ retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
discard_on ActiveJob::DeserializationError
def perform(*args)
# Might raise CustomAppException or AnotherCustomAppException for something domain specific
- # Might raise ActiveRecord::StatementInvalid when a local db deadlock is detected
+ # Might raise ActiveRecord::Deadlocked when a local db deadlock is detected
# Might raise Net::OpenTimeout when the remote service is down
end
end
diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb
index 41ce5f863b..23e237c1b7 100644
--- a/activejob/lib/active_job/arguments.rb
+++ b/activejob/lib/active_job/arguments.rb
@@ -34,8 +34,8 @@ module ActiveJob
module Arguments
extend self
# :nodoc:
- # Calls #uniq since Integer, Fixnum, and Bignum are all the same class on Ruby 2.4+
- TYPE_WHITELIST = [ NilClass, String, Integer, Fixnum, Bignum, Float, BigDecimal, TrueClass, FalseClass ].uniq
+ TYPE_WHITELIST = [ NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass ]
+ TYPE_WHITELIST.push(Fixnum, Bignum) unless 1.class == Integer
# Serializes a set of arguments. Whitelisted types are returned
# as-is. Arrays/Hashes are serialized element by element.
diff --git a/activemodel/lib/active_model/type/float.rb b/activemodel/lib/active_model/type/float.rb
index 94bb7e700c..4d0d2771a0 100644
--- a/activemodel/lib/active_model/type/float.rb
+++ b/activemodel/lib/active_model/type/float.rb
@@ -7,6 +7,15 @@ 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
diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb
index b27e84a5be..ad71c6cde8 100644
--- a/activerecord/lib/active_record/log_subscriber.rb
+++ b/activerecord/lib/active_record/log_subscriber.rb
@@ -26,9 +26,8 @@ module ActiveRecord
end
def sql(event)
- return unless logger.debug?
-
self.class.runtime += event.duration
+ return unless logger.debug?
payload = event.payload
diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb
index 387dd8e9bd..c45c8c1697 100644
--- a/activerecord/lib/active_record/query_cache.rb
+++ b/activerecord/lib/active_record/query_cache.rb
@@ -34,16 +34,14 @@ module ActiveRecord
def self.complete(enabled)
ActiveRecord::Base.connection.clear_query_cache
ActiveRecord::Base.connection.disable_query_cache! unless enabled
+
+ unless ActiveRecord::Base.connected? && ActiveRecord::Base.connection.transaction_open?
+ ActiveRecord::Base.clear_active_connections!
+ end
end
def self.install_executor_hooks(executor = ActiveSupport::Executor)
executor.register_hook(self)
-
- executor.to_complete do
- unless ActiveRecord::Base.connected? && ActiveRecord::Base.connection.transaction_open?
- ActiveRecord::Base.clear_active_connections!
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 9b692f55d2..57020e00c9 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -282,6 +282,10 @@ module ActiveRecord
end
def autosave=(autosave)
+ # autosave and inverse_of do not get along together nowadays. They may
+ # for example cause double saves. Thus, we disable this flag. If in the
+ # future those two flags are known to work well together, this could be
+ # removed.
@automatic_inverse_of = false
@options[:autosave] = autosave
parent_reflection = self.parent_reflection
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index a887be8a20..e4676f79a5 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -112,10 +112,6 @@ module ActiveRecord
# ...
# end
def calculate(operation, column_name)
- if column_name.is_a?(Symbol) && attribute_alias?(column_name)
- column_name = attribute_alias(column_name)
- end
-
if has_include?(column_name)
relation = construct_relation_for_association_calculations
relation = relation.distinct if operation.to_s.downcase == "count"
@@ -215,8 +211,8 @@ module ActiveRecord
def aggregate_column(column_name)
return column_name if Arel::Expressions === column_name
- if @klass.column_names.include?(column_name.to_s)
- Arel::Attribute.new(@klass.unscoped.table, column_name)
+ if @klass.has_attribute?(column_name.to_s) || @klass.attribute_alias?(column_name.to_s)
+ @klass.arel_attribute(column_name)
else
Arel.sql(column_name == :all ? "*" : column_name.to_s)
end
diff --git a/activerecord/test/cases/adapters/postgresql/transaction_test.rb b/activerecord/test/cases/adapters/postgresql/transaction_test.rb
index 00119f13bb..c450524de8 100644
--- a/activerecord/test/cases/adapters/postgresql/transaction_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/transaction_test.rb
@@ -28,32 +28,29 @@ module ActiveRecord
end
test "raises SerializationFailure when a serialization failure occurs" do
- with_warning_suppression do
- assert_raises(ActiveRecord::SerializationFailure) do
- thread = Thread.new do
- Sample.transaction isolation: :serializable do
- Sample.delete_all
+ assert_raises(ActiveRecord::SerializationFailure) do
+ before = Concurrent::CyclicBarrier.new(2)
+ after = Concurrent::CyclicBarrier.new(2)
- 10.times do |i|
- sleep 0.1
-
- Sample.create value: i
- end
+ thread = Thread.new do
+ with_warning_suppression do
+ Sample.transaction isolation: :serializable do
+ before.wait
+ Sample.create value: Sample.sum(:value)
+ after.wait
end
end
+ end
- sleep 0.1
-
- Sample.transaction isolation: :serializable do
- Sample.delete_all
-
- 10.times do |i|
- sleep 0.1
-
- Sample.create value: i
+ begin
+ with_warning_suppression do
+ Sample.transaction isolation: :serializable do
+ before.wait
+ Sample.create value: Sample.sum(:value)
+ after.wait
end
end
-
+ ensure
thread.join
end
end
@@ -91,10 +88,11 @@ module ActiveRecord
protected
def with_warning_suppression
- log_level = @connection.client_min_messages
- @connection.client_min_messages = "error"
+ log_level = ActiveRecord::Base.connection.client_min_messages
+ ActiveRecord::Base.connection.client_min_messages = "error"
yield
- @connection.client_min_messages = log_level
+ ensure
+ ActiveRecord::Base.connection.client_min_messages = log_level
end
end
end
diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb
index 03d781d3d2..48df931543 100644
--- a/activerecord/test/cases/migration/column_attributes_test.rb
+++ b/activerecord/test/cases/migration/column_attributes_test.rb
@@ -72,9 +72,7 @@ module ActiveRecord
assert_kind_of BigDecimal, row.wealth
# If this assert fails, that means the SELECT is broken!
- unless current_adapter?(:SQLite3Adapter)
- assert_equal correct_value, row.wealth
- end
+ assert_equal correct_value, row.wealth
# Reset to old state
TestModel.delete_all
@@ -165,7 +163,7 @@ module ActiveRecord
assert_raise(ActiveRecordError) { add_column :test_models, :integer_too_big, :integer, limit: 10 }
unless current_adapter?(:PostgreSQLAdapter)
- assert_raise(ActiveRecordError) { add_column :test_models, :text_too_big, :integer, limit: 0xfffffffff }
+ assert_raise(ActiveRecordError) { add_column :test_models, :text_too_big, :text, limit: 0xfffffffff }
end
end
end
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index 7f7faca70d..16cf2bd2d0 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -138,7 +138,7 @@ class QueryCacheTest < ActiveRecord::TestCase
assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
elsif current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter)
# Future versions of the sqlite3 adapter will return numeric
- assert_instance_of Fixnum, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
+ assert_instance_of 0.class, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
else
assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index dcaae5b462..2e18c43b1b 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -1522,7 +1522,7 @@ class RelationTest < ActiveRecord::TestCase
assert_equal Post.where(author_id: 1).to_a, author_posts.to_a
all_posts = relation.only(:limit)
- assert_equal Post.limit(1).to_a.first, all_posts.first
+ assert_equal Post.limit(1).to_a, all_posts.to_a
end
def test_anonymous_extension
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 57b1bc889a..8b604ba930 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -423,6 +423,13 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
t.datetime :datetime_with_default, default: "2014-06-05 07:17:04"
t.time :time_with_default, default: "07:17:04"
end
+
+ if current_adapter?(:PostgreSQLAdapter)
+ @connection.create_table :infinity_defaults, force: true do |t|
+ t.float :float_with_inf_default, default: Float::INFINITY
+ t.float :float_with_nan_default, default: Float::NAN
+ end
+ end
end
teardown do
@@ -438,4 +445,11 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
assert_match %r{t\.datetime\s+"datetime_with_default",\s+default: '2014-06-05 07:17:04'}, output
assert_match %r{t\.time\s+"time_with_default",\s+default: '2000-01-01 07:17:04'}, output
end
+
+ def test_schema_dump_with_float_column_infinity_default
+ skip unless current_adapter?(:PostgreSQLAdapter)
+ output = dump_table_schema('infinity_defaults')
+ assert_match %r{t\.float\s+"float_with_inf_default",\s+default: ::Float::INFINITY}, output
+ assert_match %r{t\.float\s+"float_with_nan_default",\s+default: ::Float::NAN}, output
+ end
end
diff --git a/activerecord/test/cases/type/date_time_test.rb b/activerecord/test/cases/type/date_time_test.rb
index bc4900e1c2..6848619ece 100644
--- a/activerecord/test/cases/type/date_time_test.rb
+++ b/activerecord/test/cases/type/date_time_test.rb
@@ -3,7 +3,7 @@ require "models/task"
module ActiveRecord
module Type
- class IntegerTest < ActiveRecord::TestCase
+ class DateTimeTest < ActiveRecord::TestCase
def test_datetime_seconds_precision_applied_to_timestamp
skip "This test is invalid if subsecond precision isn't supported" unless subsecond_precision_supported?
p = Task.create!(starting: ::Time.now)
diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb
index 5ac312790d..cebfda8d31 100644
--- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/conversions.rb
@@ -134,7 +134,7 @@ module ActiveSupport::NumericWithFormat
end
# Ruby 2.4+ unifies Fixnum & Bignum into Integer.
-if Integer == Fixnum
+if 0.class == Integer
Integer.prepend ActiveSupport::NumericWithFormat
else
Fixnum.prepend ActiveSupport::NumericWithFormat
diff --git a/activesupport/lib/active_support/deprecation/instance_delegator.rb b/activesupport/lib/active_support/deprecation/instance_delegator.rb
index 8efa6aabdc..6d390f3b37 100644
--- a/activesupport/lib/active_support/deprecation/instance_delegator.rb
+++ b/activesupport/lib/active_support/deprecation/instance_delegator.rb
@@ -6,6 +6,7 @@ module ActiveSupport
module InstanceDelegator # :nodoc:
def self.included(base)
base.extend(ClassMethods)
+ base.singleton_class.prepend(OverrideDelegators)
base.public_class_method :new
end
@@ -19,6 +20,18 @@ module ActiveSupport
singleton_class.delegate(method_name, to: :instance)
end
end
+
+ module OverrideDelegators # :nodoc:
+ def warn(message = nil, callstack = nil)
+ callstack ||= caller_locations(2)
+ super
+ end
+
+ def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
+ caller_backtrace ||= caller_locations(2)
+ super
+ end
+ end
end
end
end
diff --git a/activesupport/lib/active_support/execution_wrapper.rb b/activesupport/lib/active_support/execution_wrapper.rb
index 4c8b03c9df..3384d12d5b 100644
--- a/activesupport/lib/active_support/execution_wrapper.rb
+++ b/activesupport/lib/active_support/execution_wrapper.rb
@@ -19,6 +19,23 @@ module ActiveSupport
set_callback(:complete, *args, &block)
end
+ class RunHook < Struct.new(:hook) # :nodoc:
+ def before(target)
+ hook_state = target.send(:hook_state)
+ hook_state[hook] = hook.run
+ end
+ end
+
+ class CompleteHook < Struct.new(:hook) # :nodoc:
+ def before(target)
+ hook_state = target.send(:hook_state)
+ if hook_state.key?(hook)
+ hook.complete hook_state[hook]
+ end
+ end
+ alias after before
+ end
+
# Register an object to be invoked during both the +run+ and
# +complete+ steps.
#
@@ -29,19 +46,11 @@ module ActiveSupport
# invoked in that situation.)
def self.register_hook(hook, outer: false)
if outer
- run_args = [prepend: true]
- complete_args = [:after]
+ to_run RunHook.new(hook), prepend: true
+ to_complete :after, CompleteHook.new(hook)
else
- run_args = complete_args = []
- end
-
- to_run(*run_args) do
- hook_state[hook] = hook.run
- end
- to_complete(*complete_args) do
- if hook_state.key?(hook)
- hook.complete hook_state[hook]
- end
+ to_run RunHook.new(hook)
+ to_complete CompleteHook.new(hook)
end
end
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 8de8120fba..889f71c4f3 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -477,6 +477,8 @@ module ActiveSupport
end
def transfer_time_values_to_utc_constructor(time)
+ # avoid creating another Time object if possible
+ return time if time.instance_of?(::Time) && time.utc?
::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
end
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index 46b91806f6..921a3447d0 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -48,8 +48,8 @@ module ActiveSupport
}
# No need to map these on Ruby 2.4+
- TYPE_NAMES["Fixnum"] = "integer" unless Fixnum == Integer
- TYPE_NAMES["Bignum"] = "integer" unless Bignum == Integer
+ TYPE_NAMES["Fixnum"] = "integer" unless 0.class == Integer
+ TYPE_NAMES["Bignum"] = "integer" unless 0.class == Integer
end
FORMATTING = {
diff --git a/activesupport/test/core_ext/array/grouping_test.rb b/activesupport/test/core_ext/array/grouping_test.rb
index 86c9bae131..b06f87c008 100644
--- a/activesupport/test/core_ext/array/grouping_test.rb
+++ b/activesupport/test/core_ext/array/grouping_test.rb
@@ -4,11 +4,11 @@ require "active_support/core_ext/array"
class GroupingTest < ActiveSupport::TestCase
def setup
# In Ruby < 2.4, test we avoid Integer#/ (redefined by mathn)
- Fixnum.send :private, :/ unless Fixnum == Integer
+ Fixnum.send :private, :/ unless 0.class == Integer
end
def teardown
- Fixnum.send :public, :/ unless Fixnum == Integer
+ Fixnum.send :public, :/ unless 0.class == Integer
end
def test_in_groups_of_with_perfect_fit
diff --git a/activesupport/test/executor_test.rb b/activesupport/test/executor_test.rb
index 0b56ea008f..d409216206 100644
--- a/activesupport/test/executor_test.rb
+++ b/activesupport/test/executor_test.rb
@@ -158,6 +158,61 @@ class ExecutorTest < ActiveSupport::TestCase
assert_equal :some_state, supplied_state
end
+ def test_hook_insertion_order
+ invoked = []
+ supplied_state = []
+
+ hook_class = Class.new do
+ attr_accessor :letter
+
+ define_method(:initialize) do |letter|
+ self.letter = letter
+ end
+
+ define_method(:run) do
+ invoked << :"run_#{letter}"
+ :"state_#{letter}"
+ end
+
+ define_method(:complete) do |state|
+ invoked << :"complete_#{letter}"
+ supplied_state << state
+ end
+ end
+
+ executor.register_hook(hook_class.new(:a))
+ executor.register_hook(hook_class.new(:b))
+ executor.register_hook(hook_class.new(:c), outer: true)
+ executor.register_hook(hook_class.new(:d))
+
+ executor.wrap {}
+
+ assert_equal [:run_c, :run_a, :run_b, :run_d, :complete_a, :complete_b, :complete_d, :complete_c], invoked
+ assert_equal [:state_a, :state_b, :state_d, :state_c], supplied_state
+ end
+
+ def test_class_serial_is_unaffected
+ hook = Class.new do
+ define_method(:run) do
+ nil
+ end
+
+ define_method(:complete) do |state|
+ nil
+ end
+ end.new
+
+ executor.register_hook(hook)
+
+ before = RubyVM.stat(:class_serial)
+ executor.wrap {}
+ executor.wrap {}
+ executor.wrap {}
+ after = RubyVM.stat(:class_serial)
+
+ assert_equal before, after
+ end
+
def test_separate_classes_can_wrap
other_executor = Class.new(ActiveSupport::Executor)
diff --git a/guides/source/action_cable_overview.md b/guides/source/action_cable_overview.md
index 4b9a22101a..a66a8ff484 100644
--- a/guides/source/action_cable_overview.md
+++ b/guides/source/action_cable_overview.md
@@ -422,7 +422,7 @@ App.cable.subscriptions.create "AppearanceChannel",
buttonSelector = "[data-behavior~=appear_away]"
install: ->
- $(document).on "page:change.appearance", =>
+ $(document).on "turbolinks:load.appearance", =>
@appear()
$(document).on "click.appearance", buttonSelector, =>