aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--actionmailer/CHANGELOG.md8
-rw-r--r--actionview/CHANGELOG.md8
-rw-r--r--activejob/lib/active_job/callbacks.rb12
-rw-r--r--activejob/lib/active_job/core.rb2
-rw-r--r--activejob/lib/active_job/enqueuing.rb8
-rw-r--r--activejob/lib/active_job/execution.rb2
-rw-r--r--activejob/lib/active_job/logging.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/backburner_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/qu_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/que_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/resque_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sneakers_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb2
-rw-r--r--activemodel/CHANGELOG.md19
-rw-r--r--activerecord/CHANGELOG.md15
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb2
-rw-r--r--activerecord/lib/active_record/autosave_association.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb7
-rw-r--r--activerecord/lib/active_record/core.rb2
-rw-r--r--activerecord/lib/active_record/schema_dumper.rb2
-rw-r--r--activerecord/lib/active_record/type.rb1
-rw-r--r--activerecord/lib/active_record/type/decorator.rb14
-rw-r--r--activerecord/lib/active_record/type/serialized.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb26
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb8
-rw-r--r--activerecord/test/cases/autosave_association_test.rb24
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb5
-rw-r--r--activesupport/CHANGELOG.md63
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb1
-rw-r--r--activesupport/lib/active_support/duration.rb4
-rw-r--r--activesupport/test/core_ext/duration_test.rb4
-rw-r--r--guides/source/upgrading_ruby_on_rails.md44
-rw-r--r--railties/CHANGELOG.md6
-rw-r--r--railties/lib/rails/application/default_middleware_stack.rb6
-rw-r--r--railties/test/application/middleware_test.rb11
39 files changed, 257 insertions, 80 deletions
diff --git a/.travis.yml b/.travis.yml
index 985956363a..c213700687 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,9 +28,10 @@ matrix:
env: "GEM=ar:mysql"
- rvm: 2.0.0
env: "GEM=ar:mysql"
+ - rvm: ruby-head
+ env: "GEM=ar:mysql"
- rvm: rbx-2
- rvm: jruby
- - rvm: ruby-head
fast_finish: true
notifications:
email: false
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 1ff4db41a3..e5e3a0164d 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,13 +1,13 @@
-* Added #deliver_later, #deliver_now and deprecate #deliver in favour of
- #deliver_now. #deliver_later will enqueue a job to render and deliver
+* Added `#deliver_later`, `#deliver_now` and deprecate `#deliver` in favour of
+ `#deliver_now`. `#deliver_later` will enqueue a job to render and deliver
the mail instead of delivering it right at that moment. The job is enqueued
using the new Active Job framework in Rails, and will use whatever queue is
configured for Rails.
*DHH/Abdelkader Boudih/Cristian Bica*
-* Make ActionMailer::Previews methods class methods. Previously they were
- instance methods and ActionMailer tries to render a message when they
+* Make `ActionMailer::Previews` methods class methods. Previously they were
+ instance methods and `ActionMailer` tries to render a message when they
are called.
*Cristian Bica*
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 5e0b134ba4..ed58933472 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -127,12 +127,12 @@
Before:
- #=> favicon_link_tag 'myicon.ico'
+ # => favicon_link_tag 'myicon.ico'
<link href="/assets/myicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />
After:
- #=> favicon_link_tag 'myicon.ico'
+ # => favicon_link_tag 'myicon.ico'
<link href="/assets/myicon.ico" rel="shortcut icon" type="image/x-icon" />
*Geoffroy Lorieux*
@@ -145,7 +145,7 @@
*Joost Baaij*
-* `collection_check_boxes` respects `:index` option for the hidden filed name.
+* `collection_check_boxes` respects `:index` option for the hidden field name.
Fixes #14147.
@@ -166,7 +166,7 @@
*Vasiliy Ermolovich*
-* Fixed a problem where the default options for the `button_tag` helper is not
+* Fixed a problem where the default options for the `button_tag` helper are not
applied correctly.
Fixes #14254.
diff --git a/activejob/lib/active_job/callbacks.rb b/activejob/lib/active_job/callbacks.rb
index cafa3438c0..29e2a878b4 100644
--- a/activejob/lib/active_job/callbacks.rb
+++ b/activejob/lib/active_job/callbacks.rb
@@ -36,7 +36,7 @@ module ActiveJob
# def perform(video_id)
# Video.find(video_id).process
# end
- # end
+ # end
#
def before_perform(*filters, &blk)
set_callback(:perform, :before, *filters, &blk)
@@ -55,7 +55,7 @@ module ActiveJob
# def perform(video_id)
# Video.find(video_id).process
# end
- # end
+ # end
#
def after_perform(*filters, &blk)
set_callback(:perform, :after, *filters, &blk)
@@ -75,7 +75,7 @@ module ActiveJob
# def perform(video_id)
# Video.find(video_id).process
# end
- # end
+ # end
#
def around_perform(*filters, &blk)
set_callback(:perform, :around, *filters, &blk)
@@ -94,7 +94,7 @@ module ActiveJob
# def perform(video_id)
# Video.find(video_id).process
# end
- # end
+ # end
#
def before_enqueue(*filters, &blk)
set_callback(:enqueue, :before, *filters, &blk)
@@ -113,7 +113,7 @@ module ActiveJob
# def perform(video_id)
# Video.find(video_id).process
# end
- # end
+ # end
#
def after_enqueue(*filters, &blk)
set_callback(:enqueue, :after, *filters, &blk)
@@ -134,7 +134,7 @@ module ActiveJob
# def perform(video_id)
# Video.find(video_id).process
# end
- # end
+ # end
#
def around_enqueue(*filters, &blk)
set_callback(:enqueue, :around, *filters, &blk)
diff --git a/activejob/lib/active_job/core.rb b/activejob/lib/active_job/core.rb
index b6dd03a0bc..9db23cc9da 100644
--- a/activejob/lib/active_job/core.rb
+++ b/activejob/lib/active_job/core.rb
@@ -13,7 +13,7 @@ module ActiveJob
# Job Identifier
attr_accessor :job_id
- # Queue on which the job should be run on.
+ # Queue in which the job will reside.
attr_writer :queue_name
end
diff --git a/activejob/lib/active_job/enqueuing.rb b/activejob/lib/active_job/enqueuing.rb
index e8bc44cbc4..74bcc1fa5d 100644
--- a/activejob/lib/active_job/enqueuing.rb
+++ b/activejob/lib/active_job/enqueuing.rb
@@ -5,9 +5,9 @@ module ActiveJob
extend ActiveSupport::Concern
module ClassMethods
- # Push a job onto the queue. The arguments must be legal JSON types
+ # Push a job onto the queue. The arguments must be legal JSON types
# (string, int, float, nil, true, false, hash or array) or
- # GlobalID::Identification instances. Arbitrary Ruby objects
+ # GlobalID::Identification instances. Arbitrary Ruby objects
# are not supported.
#
# Returns an instance of the job class queued with args available in
@@ -22,7 +22,7 @@ module ActiveJob
end
end
- # Reschedule the job to be re-executed. This is usefull in combination
+ # Reschedule the job to be re-executed. This is useful in combination
# with the +rescue_from+ option. When you rescue an exception from your job
# you can ask Active Job to retry performing your job.
#
@@ -45,7 +45,7 @@ module ActiveJob
enqueue options
end
- # Equeue the job to be performed by the queue adapter.
+ # Enqueues the job to be performed by the queue adapter.
#
# ==== Options
# * <tt>:wait</tt> - Enqueues the job with the specified delay
diff --git a/activejob/lib/active_job/execution.rb b/activejob/lib/active_job/execution.rb
index d6d67c46e3..7ff857206d 100644
--- a/activejob/lib/active_job/execution.rb
+++ b/activejob/lib/active_job/execution.rb
@@ -22,7 +22,7 @@ module ActiveJob
end
# Performs the job immediately. The job is not sent to the queueing adapter
- # and will block the execution until it's finished.
+ # but directly executed by blocking the execution of others until it's finished.
#
# MyJob.new(*args).perform_now
def perform_now
diff --git a/activejob/lib/active_job/logging.rb b/activejob/lib/active_job/logging.rb
index 962005cd15..bb96668cfb 100644
--- a/activejob/lib/active_job/logging.rb
+++ b/activejob/lib/active_job/logging.rb
@@ -50,7 +50,7 @@ module ActiveJob
logger.formatter.current_tags.include?("ActiveJob")
end
- class LogSubscriber < ActiveSupport::LogSubscriber
+ class LogSubscriber < ActiveSupport::LogSubscriber #:nodoc:
def enqueue(event)
info do
job = event.payload[:job]
diff --git a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb
index e1b00f1de7..a07a6fc223 100644
--- a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb
@@ -14,7 +14,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
class << self
def perform(job_data)
Base.execute job_data
diff --git a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb
index 658799edfc..30c535f3b4 100644
--- a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb
@@ -13,7 +13,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
def perform(job_data)
Base.execute(job_data)
end
diff --git a/activejob/lib/active_job/queue_adapters/qu_adapter.rb b/activejob/lib/active_job/queue_adapters/qu_adapter.rb
index f681fd7e8a..5485f20689 100644
--- a/activejob/lib/active_job/queue_adapters/qu_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/qu_adapter.rb
@@ -15,7 +15,7 @@ module ActiveJob
end
end
- class JobWrapper < Qu::Job
+ class JobWrapper < Qu::Job #:nodoc:
def initialize(job_data)
@job_data = job_data
end
diff --git a/activejob/lib/active_job/queue_adapters/que_adapter.rb b/activejob/lib/active_job/queue_adapters/que_adapter.rb
index 51891ab07b..2e8a64aa87 100644
--- a/activejob/lib/active_job/queue_adapters/que_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/que_adapter.rb
@@ -13,7 +13,7 @@ module ActiveJob
end
end
- class JobWrapper < Que::Job
+ class JobWrapper < Que::Job #:nodoc:
def run(job_data)
Base.execute job_data
end
diff --git a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb
index ddcc868317..e8452938b8 100644
--- a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb
@@ -28,7 +28,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
class << self
def perform(job_data)
Base.execute job_data
diff --git a/activejob/lib/active_job/queue_adapters/resque_adapter.rb b/activejob/lib/active_job/queue_adapters/resque_adapter.rb
index affa3bdfbc..b1bc2f15ee 100644
--- a/activejob/lib/active_job/queue_adapters/resque_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/resque_adapter.rb
@@ -29,7 +29,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
class << self
def perform(job_data)
Base.execute job_data
diff --git a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
index 79926a1e24..6d351172de 100644
--- a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
@@ -23,7 +23,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
include Sidekiq::Worker
def perform(job_data)
diff --git a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
index 1ab0a87485..91658e08f0 100644
--- a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
@@ -19,7 +19,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
include Sneakers::Worker
from_queue 'default'
diff --git a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
index b19a38093f..68aa58cadb 100644
--- a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
@@ -13,7 +13,7 @@ module ActiveJob
end
end
- class JobWrapper
+ class JobWrapper #:nodoc:
include SuckerPunch::Job
def perform(job_data)
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index c14b0688c7..5588699d9b 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -12,18 +12,21 @@
* Deprecate `reset_#{attribute}` in favor of `restore_#{attribute}`.
- These methods may cause confusion with the `reset_changes` that behaves differently
- of them.
+ These methods may cause confusion with the `reset_changes`, which has
+ different behaviour.
+
+ *Rafael Mendonça França*
* Deprecate `ActiveModel::Dirty#reset_changes` in favor of `#clear_changes_information`.
- This method name is causing confusion with the `reset_#{attribute}`
- methods. While `reset_name` set the value of the name attribute for the
- previous value `reset_changes` only discard the changes and previous
- changes.
+ Method's name is causing confusion with the `reset_#{attribute}` methods.
+ While `reset_name` sets the value of the name attribute to previous value
+ `reset_changes` only discards the changes.
+
+ *Rafael Mendonça França*
-* Added `restore_attributes` method to `ActiveModel::Dirty` API to restore all the
- changed values to the previous data.
+* Added `restore_attributes` method to `ActiveModel::Dirty` API which restores
+ the value of changed attributes to previous value.
*Igor G.*
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 40eb32c059..78fb60332f 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,16 @@
+* Don't autosave unchanged has_one through records.
+
+ *Alan Kennedy*, *Steve Parrington*
+
+* Do not dump foreign keys for ignored tables. *Yves Senn*
+
+* PostgreSQL adapter correctly dumps foreign keys targeting tables
+ outside the schema search path.
+
+ Fixes #16907.
+
+ *Matthew Draper*, *Yves Senn*
+
* When a thread is killed, rollback the active transaction, instead of
committing it during the stack unwind. Previously, we could commit half-
completed work. This fix only works for Ruby 2.0+; on 1.9, we can't
@@ -9,7 +22,7 @@
* A `NullRelation` should represent nothing. This fixes a bug where
`Comment.where(post_id: Post.none)` returned a non-empty result.
- Closes #15176.
+ Fixes #15176.
*Matthew Draper*, *Yves Senn*
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index f439bd1ffe..b7fe079ef5 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -2,6 +2,8 @@ module ActiveRecord
module AttributeMethods
module TimeZoneConversion
class TimeZoneConverter < SimpleDelegator # :nodoc:
+ include Type::Decorator
+
def type_cast_from_database(value)
convert_time_to_time_zone(super)
end
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index a8e4d25df2..c384e8c413 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -403,7 +403,9 @@ module ActiveRecord
# If the record is new or it has changed, returns true.
def record_changed?(reflection, record, key)
- record.new_record? || record[reflection.foreign_key] != key || record.attribute_changed?(reflection.foreign_key)
+ record.new_record? ||
+ (record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key) ||
+ record.attribute_changed?(reflection.foreign_key)
end
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 767b6b614a..799aafbd99 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -60,8 +60,8 @@ module ActiveRecord
def create_database(name, options = {})
options = { encoding: 'utf8' }.merge!(options.symbolize_keys)
- option_string = options.sum do |key, value|
- case key
+ option_string = options.inject("") do |memo, (key, value)|
+ memo += case key
when :owner
" OWNER = \"#{value}\""
when :template
@@ -466,7 +466,7 @@ module ActiveRecord
def foreign_keys(table_name)
fk_info = select_all <<-SQL.strip_heredoc
- SELECT t2.relname AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
+ SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
FROM pg_constraint c
JOIN pg_class t1 ON c.conrelid = t1.oid
JOIN pg_class t2 ON c.confrelid = t2.oid
@@ -488,6 +488,7 @@ module ActiveRecord
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
options[:on_update] = extract_foreign_key_action(row['on_update'])
+
ForeignKeyDefinition.new(table_name, row['to_table'], options)
end
end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 83859e474a..61f1a9aa27 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -124,6 +124,8 @@ module ActiveRecord
def find(*ids)
# We don't have cache keys for this stuff yet
return super unless ids.length == 1
+ # Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
+ return super if ids.first.kind_of?(Symbol)
return super if block_given? ||
primary_key.nil? ||
default_scopes.any? ||
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index 68d976c240..82c5ca291c 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -100,7 +100,7 @@ HEADER
# dump foreign keys at the end to make sure all dependent tables exist.
if @connection.supports_foreign_keys?
sorted_tables.each do |tbl|
- foreign_keys(tbl, stream)
+ foreign_keys(tbl, stream) unless ignored?(tbl)
end
end
end
diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb
index f1384e0bb2..e3d6c5957e 100644
--- a/activerecord/lib/active_record/type.rb
+++ b/activerecord/lib/active_record/type.rb
@@ -1,3 +1,4 @@
+require 'active_record/type/decorator'
require 'active_record/type/mutable'
require 'active_record/type/numeric'
require 'active_record/type/time_value'
diff --git a/activerecord/lib/active_record/type/decorator.rb b/activerecord/lib/active_record/type/decorator.rb
new file mode 100644
index 0000000000..9fce38ea44
--- /dev/null
+++ b/activerecord/lib/active_record/type/decorator.rb
@@ -0,0 +1,14 @@
+module ActiveRecord
+ module Type
+ module Decorator # :nodoc:
+ def init_with(coder)
+ @subtype = coder['subtype']
+ __setobj__(@subtype)
+ end
+
+ def encode_with(coder)
+ coder['subtype'] = __getobj__
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb
index 5b512433b0..17004b3593 100644
--- a/activerecord/lib/active_record/type/serialized.rb
+++ b/activerecord/lib/active_record/type/serialized.rb
@@ -2,6 +2,7 @@ module ActiveRecord
module Type
class Serialized < SimpleDelegator # :nodoc:
include Mutable
+ include Decorator
attr_reader :subtype, :coder
@@ -36,14 +37,13 @@ module ActiveRecord
end
def init_with(coder)
- @subtype = coder['subtype']
@coder = coder['coder']
- __setobj__(@subtype)
+ super
end
def encode_with(coder)
- coder['subtype'] = @subtype
coder['coder'] = @coder
+ super
end
private
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index 9e5fd17dc4..6f40b0d2de 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'support/schema_dumping_helper'
class SchemaTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
@@ -426,3 +427,28 @@ class SchemaTest < ActiveRecord::TestCase
assert_equal this_index_name, this_index.name
end
end
+
+class SchemaForeignKeyTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
+
+ setup do
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def test_dump_foreign_key_targeting_different_schema
+ @connection.create_schema "my_schema"
+ @connection.create_table "my_schema.trains" do |t|
+ t.string :name
+ end
+ @connection.create_table "wagons" do |t|
+ t.integer :train_id
+ end
+ @connection.add_foreign_key "wagons", "my_schema.trains", column: "train_id"
+ output = dump_table_schema "wagons"
+ assert_match %r{\s+add_foreign_key "wagons", "my_schema.trains", column: "train_id"$}, output
+ ensure
+ @connection.execute "DROP TABLE IF EXISTS wagons"
+ @connection.execute "DROP TABLE IF EXISTS my_schema.trains"
+ @connection.execute "DROP SCHEMA IF EXISTS my_schema"
+ end
+end
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index b4917e727a..153f870e3d 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -681,6 +681,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
+ def test_yaml_dumping_record_with_time_zone_aware_attribute
+ in_time_zone "Pacific Time (US & Canada)" do
+ record = Topic.new(id: 1)
+ record.written_on = "Jan 01 00:00:00 2014"
+ assert_equal record, YAML.load(YAML.dump(record))
+ end
+ end
+
def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
Topic.skip_time_zone_conversion_for_attributes = [:field_a]
Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 025cdbeba9..b2a7d3956d 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -19,6 +19,9 @@ require 'models/treasure'
require 'models/eye'
require 'models/electron'
require 'models/molecule'
+require 'models/member'
+require 'models/member_detail'
+require 'models/organization'
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
def test_autosave_validation
@@ -1116,6 +1119,27 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
end
end
+class TestAutosaveAssociationOnAHasOneThroughAssociation < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false unless supports_savepoints?
+
+ def setup
+ super
+ organization = Organization.create
+ @member = Member.create
+ MemberDetail.create(organization: organization, member: @member)
+ end
+
+ def test_should_not_has_one_through_model
+ class << @member.organization
+ def save(*args)
+ super
+ raise 'Oh noes!'
+ end
+ end
+ assert_nothing_raised { @member.save }
+ end
+end
+
class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
self.use_transactional_fixtures = false unless supports_savepoints?
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index d7ee56374d..93fb502410 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -371,6 +371,11 @@ class SchemaDumperTest < ActiveRecord::TestCase
output = standard_dump
assert_match(/^\s+add_foreign_key "fk_test_has_fk"[^\n]+\n\s+add_foreign_key "lessons_students"/, output)
end
+
+ def test_do_not_dump_foreign_keys_for_ignored_tables
+ output = dump_table_schema "authors"
+ assert_equal ["authors"], output.scan(/^\s*add_foreign_key "([^"]+)".+$/).flatten
+ end
end
class CreateDogMigration < ActiveRecord::Migration
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index bc8d11a297..8f328335b2 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,18 @@
+* Added method `#eql?` to `ActiveSupport::Duration`, in addition to `#==`.
+
+ Currently, the following returns `false`, contrary to expectation:
+
+ 1.minute.eql?(1.minute)
+
+ Adding method `#eql?` will make this behave like expected. Method `#eql?` is
+ just a bit stricter than `#==`, as it checks whether the argument is also a duration. Their
+ parts may be different though.
+
+ 1.minute.eql?(60.seconds) # => true
+ 1.minute.eql?(60) # => false
+
+ *Joost Lubach*
+
* Time#change can now change nanoseconds (:nsec) as a higher-precision
alternative to microseconds (:usec).
@@ -9,7 +24,7 @@
*Kostiantyn Kahanskyi*
* Introduced new configuration option `active_support.test_order` for
- specifying the order test cases are executed. This option currently defaults
+ specifying the order in which test cases are executed. This option currently defaults
to `:sorted` but will be changed to `:random` in Rails 5.0.
*Akira Matsuda*, *Godfrey Chan*
@@ -32,7 +47,7 @@
*Peter Jaros*
* `determine_constant_from_test_name` does no longer shadow `NameError`s
- which happen during constant autoloading.
+ which happens during constant autoloading.
Fixes #9933.
@@ -110,8 +125,8 @@
* Always instrument `ActiveSupport::Cache`.
- Since `ActiveSupport::Notifications` only instrument items when there
- are subscriber we don't need to disable instrumentation.
+ Since `ActiveSupport::Notifications` only instruments items when there
+ are attached subscribers, we don't need to disable instrumentation.
*Peter Wagenet*
@@ -134,17 +149,17 @@
`ActiveSupport::TimeWithZone#-` should return the same result as if we were
using `Time#-`:
- Time.now.end_of_day - Time.now.beginning_of_day #=> 86399.999999999
+ Time.now.end_of_day - Time.now.beginning_of_day # => 86399.999999999
Before:
- Time.zone.now.end_of_day.nsec #=> 999999999
- Time.zone.now.end_of_day - Time.zone.now.beginning_of_day #=> 86400.0
+ Time.zone.now.end_of_day.nsec # => 999999999
+ Time.zone.now.end_of_day - Time.zone.now.beginning_of_day # => 86400.0
After:
Time.zone.now.end_of_day - Time.zone.now.beginning_of_day
- #=> 86399.999999999
+ # => 86399.999999999
*Gordon Chan*
@@ -153,12 +168,12 @@
Before:
ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2
- #=> "330.00"
+ # => "330.00"
After:
ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2
- #=> "333.33"
+ # => "333.33"
See #15379.
@@ -240,9 +255,9 @@
*Xavier Noria*
-* Fixed backward compatibility isues introduced in 326e652.
+* Fixed backward compatibility issues introduced in 326e652.
- Empty Hash or Array should not present in serialization result.
+ Empty Hash or Array should not be present in serialization result.
{a: []}.to_query # => ""
{a: {}}.to_query # => ""
@@ -261,20 +276,20 @@
This fixes the current situation of:
- 1.second.eql?(1.second) #=> false
+ 1.second.eql?(1.second) # => false
`eql?` also requires that the other object is an `ActiveSupport::Duration`.
This requirement makes `ActiveSupport::Duration`'s behavior consistent with
the behavior of Ruby's numeric types:
- 1.eql?(1.0) #=> false
- 1.0.eql?(1) #=> false
+ 1.eql?(1.0) # => false
+ 1.0.eql?(1) # => false
- 1.second.eql?(1) #=> false (was true)
- 1.eql?(1.second) #=> false
+ 1.second.eql?(1) # => false (was true)
+ 1.eql?(1.second) # => false
{ 1 => "foo", 1.0 => "bar" }
- #=> { 1 => "foo", 1.0 => "bar" }
+ # => { 1 => "foo", 1.0 => "bar" }
{ 1 => "foo", 1.second => "bar" }
# now => { 1 => "foo", 1.second => "bar" }
@@ -282,11 +297,11 @@
And though the behavior of these hasn't changed, for reference:
- 1 == 1.0 #=> true
- 1.0 == 1 #=> true
+ 1 == 1.0 # => true
+ 1.0 == 1 # => true
- 1 == 1.second #=> true
- 1.second == 1 #=> true
+ 1 == 1.second # => true
+ 1.second == 1 # => true
*Emily Dobervich*
@@ -296,8 +311,8 @@
*Pavel Pravosud*
-* `HashWithIndifferentAccess` better respects `#to_hash` on objects it's
- given. In particular, `.new`, `#update`, `#merge`, `#replace` all accept
+* `HashWithIndifferentAccess` better respects `#to_hash` on objects it
+ recieves. In particular, `.new`, `#update`, `#merge`, `#replace` all accept
objects which respond to `#to_hash`, even if those objects are not Hashes
directly.
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index a943752f17..38d567c014 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -199,6 +199,7 @@ class String
# 'employee_salary'.humanize # => "Employee salary"
# 'author_id'.humanize # => "Author"
# 'author_id'.humanize(capitalize: false) # => "author"
+ # '_id'.humanize # => "Id"
def humanize(options = {})
ActiveSupport::Inflector.humanize(self, options)
end
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index a54494bc65..e861a17426 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -57,8 +57,10 @@ module ActiveSupport
@value.to_s
end
+ # Returns +true+ if +other+ is also a Duration instance, which has the
+ # same parts as this one.
def eql?(other)
- other.is_a?(Duration) && self == other
+ Duration === other && other.value.eql?(value)
end
def self.===(other) #:nodoc:
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index 555bde6e04..881faf93f5 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -49,9 +49,13 @@ class DurationTest < ActiveSupport::TestCase
"which behaves oddly for the sake of backward-compatibility."
assert 1.minute.eql?(1.minute)
+ assert 1.minute.eql?(60.seconds)
assert 2.days.eql?(48.hours)
assert !1.second.eql?(1)
assert !1.eql?(1.second)
+ assert 1.minute.eql?(180.seconds - 2.minutes)
+ assert !1.minute.eql?(60)
+ assert !1.minute.eql?('foo')
end
def test_inspect
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 2c6797d1fd..4e538693f7 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -55,15 +55,51 @@ a [pull request](https://github.com/rails/rails/edit/master/guides/source/upgrad
### Web Console
-First, add `gem 'web-console', '~> 2.0.0.beta3'` to the `:development` group in your Gemfile and run `bundle install` (it won't have been included when you upgraded Rails). Once it's been installed, you can simply drop a reference to the console helper (i.e., `<%= console %>`) into any view you want to enable it for. A console will also be provided on any error page you view in your development environment.
+First, add `gem 'web-console', '~> 2.0'` to the `:development` group in your Gemfile and run `bundle install` (it won't have been included when you upgraded Rails). Once it's been installed, you can simply drop a reference to the console helper (i.e., `<%= console %>`) into any view you want to enable it for. A console will also be provided on any error page you view in your development environment.
-Additionally, you can tell Rails to automatically mount a VT100-compatible console on a predetermined path by setting `config.web_console.automount = true` in your `config/environments/development.rb`. You can specify the path by setting `config.web_console.default_mount_path` (note that this defaults to `/console`).
+Additionally, you can tell Rails to automatically mount a VT100-compatible console on a predetermined path by setting the appropriate configuration flags in your development config:
-TODO: Update `web-console` version to release version.
+```ruby
+# config/environments/development.rb
+
+config.web_console.automount = true
+config.web_console.default_mount_path = '/terminal' # Optional, defaults to /console
+```
### Responders
-TODO: mention https://github.com/rails/rails/pull/16526
+`respond_with` and the class-level `respond_to` methods have been extracted to the `responders` gem. To use them, simply add `gem 'responders', '~> 2.0'` to your Gemfile. Calls to `respond_with` and `respond_to` (again, at the class level) will no longer work without having included the `responders` gem in your dependencies:
+
+```ruby
+# app/controllers/users_controller.rb
+
+class UsersController < ApplicationController
+ respond_to :html, :json
+
+ def show
+ @user = User.find(params[:id])
+ respond_with @user
+ end
+end
+```
+
+Instance-level `respond_to` is unaffected and does not require the additional gem:
+
+```ruby
+# app/controllers/users_controller.rb
+
+class UsersController < ApplicationController
+ def show
+ @user = User.find(params[:id])
+ respond_to do |format|
+ format.html
+ format.json { render json: @user }
+ end
+ end
+end
+```
+
+See [#16526](https://github.com/rails/rails/pull/16526) for more details.
### Error handling in transaction callbacks
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index f83824ccd0..0543b57ad4 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -4,6 +4,12 @@
*Yukio Mizuta*
+* Inject `Rack::Lock` if `config.eager_load` is false.
+
+ Fixes #15089.
+
+ *Xavier Noria*
+
* Change the path of dummy app location in plugin's test_helper.rb for cases
you specify dummy_path option.
diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb
index a00afe008c..d1789192ef 100644
--- a/railties/lib/rails/application/default_middleware_stack.rb
+++ b/railties/lib/rails/application/default_middleware_stack.rb
@@ -66,7 +66,11 @@ module Rails
end
def allow_concurrency?
- config.allow_concurrency.nil? ? config.cache_classes : config.allow_concurrency
+ if config.allow_concurrency.nil?
+ config.cache_classes && config.eager_load
+ else
+ config.allow_concurrency
+ end
end
def load_rack_cache
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index a905598d80..caef39d16f 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -94,13 +94,20 @@ module ApplicationTests
assert !middleware.include?("ActiveRecord::Migration::CheckPending")
end
- test "removes lock if cache classes is set" do
+ test "includes lock if cache_classes is set but eager_load is not" do
add_to_config "config.cache_classes = true"
boot!
+ assert middleware.include?("Rack::Lock")
+ end
+
+ test "does not include lock if cache_classes is set and so is eager_load" do
+ add_to_config "config.cache_classes = true"
+ add_to_config "config.eager_load = true"
+ boot!
assert !middleware.include?("Rack::Lock")
end
- test "removes lock if allow concurrency is set" do
+ test "does not include lock if allow_concurrency is set" do
add_to_config "config.allow_concurrency = true"
boot!
assert !middleware.include?("Rack::Lock")