aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock12
-rw-r--r--actionmailer/lib/action_mailer/test_helper.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb3
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb1
-rw-r--r--actionpack/test/dispatch/ssl_test.rb8
-rw-r--r--actionview/lib/action_view/digestor.rb6
-rw-r--r--actionview/lib/action_view/helpers/tags/base.rb6
-rw-r--r--actionview/lib/action_view/helpers/translation_helper.rb7
-rw-r--r--actionview/test/activerecord/multifetch_cache_test.rb35
-rw-r--r--actionview/test/fixtures/digestor/comments/show.js.erb1
-rw-r--r--actionview/test/template/digestor_test.rb12
-rw-r--r--activejob/CHANGELOG.md8
-rw-r--r--activejob/README.md6
-rw-r--r--activejob/Rakefile1
-rw-r--r--activejob/lib/active_job/queue_adapters.rb4
-rw-r--r--activejob/lib/active_job/queue_adapters/qu_adapter.rb46
-rw-r--r--activejob/test/adapters/qu.rb5
-rw-r--r--activejob/test/integration/queuing_test.rb2
-rw-r--r--activejob/test/support/integration/adapters/qu.rb40
-rw-r--r--activemodel/lib/active_model/type/time.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb2
-rw-r--r--activerecord/lib/active_record/connection_handling.rb4
-rw-r--r--activerecord/lib/active_record/railtie.rb7
-rw-r--r--activerecord/lib/active_record/railties/collection_cache_association_loading.rb34
-rw-r--r--activerecord/lib/active_record/relation.rb21
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb5
-rw-r--r--activerecord/lib/active_record/store.rb4
-rw-r--r--activerecord/test/cases/adapters/sqlite3/quoting_test.rb7
-rw-r--r--activerecord/test/cases/connection_adapters/connection_handler_test.rb48
-rw-r--r--activerecord/test/cases/date_time_precision_test.rb18
-rw-r--r--activerecord/test/cases/quoting_test.rb39
-rw-r--r--activerecord/test/cases/relation/mutation_test.rb7
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb2
-rw-r--r--activerecord/test/cases/time_precision_test.rb18
-rw-r--r--activerecord/test/schema/schema.rb2
-rw-r--r--activestorage/lib/active_storage/service/s3_service.rb4
-rw-r--r--activestorage/test/service/s3_service_test.rb2
-rw-r--r--activesupport/lib/active_support/cache.rb27
-rw-r--r--activesupport/lib/active_support/cache/redis_cache_store.rb2
-rw-r--r--guides/source/5_2_release_notes.md220
-rw-r--r--guides/source/active_job_basics.md2
-rw-r--r--guides/source/active_storage_overview.md7
-rw-r--r--guides/source/caching_with_rails.md48
-rw-r--r--guides/source/getting_started.md8
-rw-r--r--guides/source/security.md106
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb2
53 files changed, 478 insertions, 403 deletions
diff --git a/Gemfile b/Gemfile
index c699b8b942..0730c1e9b0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -45,7 +45,7 @@ group :doc do
end
# Active Support.
-gem "dalli", ">= 2.2.1"
+gem "dalli", "< 2.7.7"
gem "listen", ">= 3.0.5", "< 3.2", require: false
gem "libxml-ruby", platforms: :ruby
gem "connection_pool", require: false
@@ -64,9 +64,6 @@ group :job do
gem "sneakers", require: false
gem "que", require: false
gem "backburner", require: false
- # TODO: add qu after it support Rails 5.1
- # gem 'qu-rails', github: "bkeepers/qu", branch: "master", require: false
- # gem "qu-redis", require: false
gem "delayed_job_active_record", require: false
gem "sequel", require: false
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 58d751c4c3..4f0c512114 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -285,7 +285,7 @@ GEM
logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
- loofah (2.1.1)
+ loofah (2.2.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
@@ -324,12 +324,12 @@ GEM
mysql2 (0.4.10-x86-mingw32)
nio4r (2.2.0)
nio4r (2.2.0-java)
- nokogiri (1.8.1)
+ nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
- nokogiri (1.8.1-java)
- nokogiri (1.8.1-x64-mingw32)
+ nokogiri (1.8.2-java)
+ nokogiri (1.8.2-x64-mingw32)
mini_portile2 (~> 2.3.0)
- nokogiri (1.8.1-x86-mingw32)
+ nokogiri (1.8.2-x86-mingw32)
mini_portile2 (~> 2.3.0)
os (0.9.6)
parallel (1.12.1)
@@ -510,7 +510,7 @@ DEPENDENCIES
chromedriver-helper
coffee-rails
connection_pool
- dalli (>= 2.2.1)
+ dalli (< 2.7.7)
delayed_job
delayed_job_active_record
google-cloud-storage (~> 1.8)
diff --git a/actionmailer/lib/action_mailer/test_helper.rb b/actionmailer/lib/action_mailer/test_helper.rb
index ec748236b4..e9ddef3b94 100644
--- a/actionmailer/lib/action_mailer/test_helper.rb
+++ b/actionmailer/lib/action_mailer/test_helper.rb
@@ -14,7 +14,7 @@ module ActionMailer
# assert_emails 0
# ContactMailer.welcome.deliver_now
# assert_emails 1
- # ContactMailer.welcome.deliver_later
+ # ContactMailer.welcome.deliver_now
# assert_emails 2
# end
#
@@ -38,9 +38,7 @@ module ActionMailer
new_count = ActionMailer::Base.deliveries.size
assert_equal number, new_count - original_count, "#{number} emails expected, but #{new_count - original_count} were sent"
else
- perform_enqueued_jobs(only: [ActionMailer::DeliveryJob, ActionMailer::Parameterized::DeliveryJob]) do
- assert_equal number, ActionMailer::Base.deliveries.size
- end
+ assert_equal number, ActionMailer::Base.deliveries.size
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 6d9f36ad75..240269d1c7 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -15,6 +15,8 @@ module ActionDispatch
#
# config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }
#
+ # Cookies will not be flagged as secure for excluded requests.
+ #
# 2. <b>Secure cookies</b>: Sets the +secure+ flag on cookies to tell browsers they
# must not be sent along with +http://+ requests. Enabled by default. Set
# +config.ssl_options+ with <tt>secure_cookies: false</tt> to disable this feature.
@@ -71,7 +73,7 @@ module ActionDispatch
if request.ssl?
@app.call(env).tap do |status, headers, body|
set_hsts_header! headers
- flag_cookies_as_secure! headers if @secure_cookies
+ flag_cookies_as_secure! headers if @secure_cookies && !@exclude.call(request)
end
else
return redirect_to_https request unless @exclude.call(request)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index f3970d5445..d9dd24935b 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -664,6 +664,7 @@ module ActionDispatch
def define_generate_prefix(app, name)
_route = @set.named_routes.get name
_routes = @set
+ _url_helpers = @set.url_helpers
script_namer = ->(options) do
prefix_options = options.slice(*_route.segment_keys)
@@ -675,7 +676,7 @@ module ActionDispatch
# We must actually delete prefix segment keys to avoid passing them to next url_for.
_route.segment_keys.each { |k| options.delete(k) }
- _routes.url_helpers.send("#{name}_path", prefix_options)
+ _url_helpers.send("#{name}_path", prefix_options)
end
app.routes.define_mounted_helper(name, script_namer)
diff --git a/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb b/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb
index ffa85f4e14..e47d5020f4 100644
--- a/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb
+++ b/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb
@@ -19,6 +19,7 @@ module ActionDispatch
def after_teardown
take_failed_screenshot
Capybara.reset_sessions!
+ ensure
super
end
end
diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb
index 90f2ee46ea..baf46e7c7e 100644
--- a/actionpack/test/dispatch/ssl_test.rb
+++ b/actionpack/test/dispatch/ssl_test.rb
@@ -208,6 +208,14 @@ class SecureCookiesTest < SSLTest
assert_cookies(*DEFAULT.split("\n"))
end
+ def test_cookies_as_not_secure_with_exclude
+ excluding = { exclude: -> request { request.domain =~ /example/ } }
+ get headers: { "Set-Cookie" => DEFAULT }, ssl_options: { redirect: excluding }
+
+ assert_cookies(*DEFAULT.split("\n"))
+ assert_response :ok
+ end
+
def test_no_cookies
get
assert_nil response.headers["Set-Cookie"]
diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb
index 1cf0bd3016..dbd7a4ee11 100644
--- a/actionview/lib/action_view/digestor.rb
+++ b/actionview/lib/action_view/digestor.rb
@@ -45,11 +45,9 @@ module ActionView
# Create a dependency tree for template named +name+.
def tree(name, finder, partial = false, seen = {})
logical_name = name.gsub(%r|/_|, "/")
+ finder.formats = [finder.rendered_format] if finder.rendered_format
- options = {}
- options[:formats] = [finder.rendered_format] if finder.rendered_format
-
- if template = finder.disable_cache { finder.find_all(logical_name, [], partial, [], options).first }
+ if template = finder.disable_cache { finder.find_all(logical_name, [], partial, []).first }
finder.rendered_format ||= template.formats.first
if node = seen[template.identifier] # handle cycles in the tree
diff --git a/actionview/lib/action_view/helpers/tags/base.rb b/actionview/lib/action_view/helpers/tags/base.rb
index f1eca2268a..eef527d36f 100644
--- a/actionview/lib/action_view/helpers/tags/base.rb
+++ b/actionview/lib/action_view/helpers/tags/base.rb
@@ -109,11 +109,11 @@ module ActionView
# a little duplication to construct less strings
case
when @object_name.empty?
- "#{sanitized_method_name}#{"[]" if multiple}"
+ "#{sanitized_method_name}#{multiple ? "[]" : ""}"
when index
- "#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}"
+ "#{@object_name}[#{index}][#{sanitized_method_name}]#{multiple ? "[]" : ""}"
else
- "#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
+ "#{@object_name}[#{sanitized_method_name}]#{multiple ? "[]" : ""}"
end
end
diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb
index 1860bc4732..80cb73d683 100644
--- a/actionview/lib/action_view/helpers/translation_helper.rb
+++ b/actionview/lib/action_view/helpers/translation_helper.rb
@@ -122,9 +122,12 @@ module ActionView
private
def scope_key_by_partial(key)
- if key.to_s.first == "."
+ stringified_key = key.to_s
+ if stringified_key.first == "."
if @virtual_path
- @virtual_path.gsub(%r{/_?}, ".") + key.to_s
+ @_scope_key_by_partial_cache ||= {}
+ @_scope_key_by_partial_cache[@virtual_path] ||= @virtual_path.gsub(%r{/_?}, ".")
+ "#{@_scope_key_by_partial_cache[@virtual_path]}#{stringified_key}"
else
raise "Cannot use t(#{key.inspect}) shortcut because path is not available"
end
diff --git a/actionview/test/activerecord/multifetch_cache_test.rb b/actionview/test/activerecord/multifetch_cache_test.rb
new file mode 100644
index 0000000000..12be069e69
--- /dev/null
+++ b/actionview/test/activerecord/multifetch_cache_test.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require "active_record_unit"
+require "active_record/railties/collection_cache_association_loading"
+
+ActionView::PartialRenderer.prepend(ActiveRecord::Railties::CollectionCacheAssociationLoading)
+
+class MultifetchCacheTest < ActiveRecordTestCase
+ fixtures :topics, :replies
+
+ def setup
+ view_paths = ActionController::Base.view_paths
+
+ @view = Class.new(ActionView::Base) do
+ def view_cache_dependencies
+ []
+ end
+
+ def combined_fragment_cache_key(key)
+ [ :views, key ]
+ end
+ end.new(view_paths, {})
+ end
+
+ def test_only_preloading_for_records_that_miss_the_cache
+ @view.render partial: "test/partial", collection: [topics(:rails)], cached: true
+
+ @topics = Topic.preload(:replies)
+
+ @view.render partial: "test/partial", collection: @topics, cached: true
+
+ assert_not @topics.detect { |topic| topic.id == topics(:rails).id }.replies.loaded?
+ assert @topics.detect { |topic| topic.id != topics(:rails).id }.replies.loaded?
+ end
+end
diff --git a/actionview/test/fixtures/digestor/comments/show.js.erb b/actionview/test/fixtures/digestor/comments/show.js.erb
new file mode 100644
index 0000000000..38b37dfa2b
--- /dev/null
+++ b/actionview/test/fixtures/digestor/comments/show.js.erb
@@ -0,0 +1 @@
+alert("<%=j render("comments/comment") %>")
diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb
index 1bfa39a319..ddaa7febb3 100644
--- a/actionview/test/template/digestor_test.rb
+++ b/actionview/test/template/digestor_test.rb
@@ -160,6 +160,18 @@ class TemplateDigestorTest < ActionView::TestCase
assert_equal [:html], tree_template_formats("messages/show").uniq
end
+ def test_template_dependencies_with_fallback_from_js_to_html_format
+ finder.rendered_format = :js
+ assert_equal ["comments/comment"], dependencies("comments/show")
+ end
+
+ def test_template_digest_with_fallback_from_js_to_html_format
+ finder.rendered_format = :js
+ assert_digest_difference("comments/show") do
+ change_template("comments/_comment")
+ end
+ end
+
def test_recursion_in_renders
assert digest("level/recursion") # assert recursion is possible
assert_not_nil digest("level/recursion") # assert digest is stored
diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md
index 4e832eca20..a3d13ad162 100644
--- a/activejob/CHANGELOG.md
+++ b/activejob/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Remove support for Qu gem.
+
+ Reasons are that the Qu gem wasn't compatible since Rails 5.1,
+ gem development was stopped in 2014 and maintainers have
+ confirmed its demise. See issue #32273
+
+ *Alberto Almagro*
+
* Add support for timezones to Active Job.
Record what was the current timezone in effect when the job was
diff --git a/activejob/README.md b/activejob/README.md
index f1ebb76e08..d49fcfe3c2 100644
--- a/activejob/README.md
+++ b/activejob/README.md
@@ -88,6 +88,12 @@ Active Job has built-in adapters for multiple queueing backends (Sidekiq,
Resque, Delayed Job and others). To get an up-to-date list of the adapters
see the API Documentation for [ActiveJob::QueueAdapters](http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
+**Please note:** We are not accepting pull requests for new adapters. We
+encourage library authors to provide an ActiveJob adapter as part of
+their gem, or as a stand-alone gem. For discussion about this see the
+following PRs: [23311](https://github.com/rails/rails/issues/23311#issuecomment-176275718),
+[21406](https://github.com/rails/rails/pull/21406#issuecomment-138813484), and [#32285](https://github.com/rails/rails/pull/32285).
+
## Auxiliary gems
* [activejob-stats](https://github.com/seuros/activejob-stats)
diff --git a/activejob/Rakefile b/activejob/Rakefile
index 77f3e7f8ff..b4da75adab 100644
--- a/activejob/Rakefile
+++ b/activejob/Rakefile
@@ -2,7 +2,6 @@
require "rake/testtask"
-# TODO: add qu back to the list after it support Rails 5.1
ACTIVEJOB_ADAPTERS = %w(async inline delayed_job que queue_classic resque sidekiq sneakers sucker_punch backburner test)
ACTIVEJOB_ADAPTERS.delete("queue_classic") if defined?(JRUBY_VERSION)
diff --git a/activejob/lib/active_job/queue_adapters.rb b/activejob/lib/active_job/queue_adapters.rb
index c1a1d3c510..7854467cc1 100644
--- a/activejob/lib/active_job/queue_adapters.rb
+++ b/activejob/lib/active_job/queue_adapters.rb
@@ -7,7 +7,6 @@ module ActiveJob
#
# * {Backburner}[https://github.com/nesquena/backburner]
# * {Delayed Job}[https://github.com/collectiveidea/delayed_job]
- # * {Qu}[https://github.com/bkeepers/qu]
# * {Que}[https://github.com/chanks/que]
# * {queue_classic}[https://github.com/QueueClassic/queue_classic]
# * {Resque}[https://github.com/resque/resque]
@@ -16,6 +15,7 @@ module ActiveJob
# * {Sucker Punch}[https://github.com/brandonhilkert/sucker_punch]
# * {Active Job Async Job}[http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html]
# * {Active Job Inline}[http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html]
+ # * Please Note: We are not accepting pull requests for new adapters. See the README for more details.
#
# === Backends Features
#
@@ -23,7 +23,6 @@ module ActiveJob
# |-------------------|-------|--------|------------|------------|---------|---------|
# | Backburner | Yes | Yes | Yes | Yes | Job | Global |
# | Delayed Job | Yes | Yes | Yes | Job | Global | Global |
- # | Qu | Yes | Yes | No | No | No | Global |
# | Que | Yes | Yes | Yes | Job | No | Job |
# | queue_classic | Yes | Yes | Yes* | No | No | No |
# | Resque | Yes | Yes | Yes (Gem) | Queue | Global | Yes |
@@ -114,7 +113,6 @@ module ActiveJob
autoload :InlineAdapter
autoload :BackburnerAdapter
autoload :DelayedJobAdapter
- autoload :QuAdapter
autoload :QueAdapter
autoload :QueueClassicAdapter
autoload :ResqueAdapter
diff --git a/activejob/lib/active_job/queue_adapters/qu_adapter.rb b/activejob/lib/active_job/queue_adapters/qu_adapter.rb
deleted file mode 100644
index bd7003e177..0000000000
--- a/activejob/lib/active_job/queue_adapters/qu_adapter.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require "qu"
-
-module ActiveJob
- module QueueAdapters
- # == Qu adapter for Active Job
- #
- # Qu is a Ruby library for queuing and processing background jobs. It is
- # heavily inspired by delayed_job and Resque. Qu was created to overcome
- # some shortcomings in the existing queuing libraries.
- # The advantages of Qu are: Multiple backends (redis, mongo), jobs are
- # requeued when worker is killed, resque-like API.
- #
- # Read more about Qu {here}[https://github.com/bkeepers/qu].
- #
- # To use Qu set the queue_adapter config to +:qu+.
- #
- # Rails.application.config.active_job.queue_adapter = :qu
- class QuAdapter
- def enqueue(job, *args) #:nodoc:
- qu_job = Qu::Payload.new(klass: JobWrapper, args: [job.serialize]).tap do |payload|
- payload.instance_variable_set(:@queue, job.queue_name)
- end.push
-
- # qu_job can be nil depending on the configured backend
- job.provider_job_id = qu_job.id unless qu_job.nil?
- qu_job
- end
-
- def enqueue_at(job, timestamp, *args) #:nodoc:
- raise NotImplementedError, "This queueing backend does not support scheduling jobs. To see what features are supported go to http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html"
- end
-
- class JobWrapper < Qu::Job #:nodoc:
- def initialize(job_data)
- @job_data = job_data
- end
-
- def perform
- Base.execute @job_data
- end
- end
- end
- end
-end
diff --git a/activejob/test/adapters/qu.rb b/activejob/test/adapters/qu.rb
deleted file mode 100644
index 5b471fa347..0000000000
--- a/activejob/test/adapters/qu.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-require "qu-immediate"
-
-ActiveJob::Base.queue_adapter = :qu
diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb
index 7a95d3d039..32afb5ca62 100644
--- a/activejob/test/integration/queuing_test.rb
+++ b/activejob/test/integration/queuing_test.rb
@@ -82,7 +82,7 @@ class QueuingTest < ActiveSupport::TestCase
end
test "should supply a provider_job_id when available for immediate jobs" do
- skip unless adapter_is?(:async, :delayed_job, :sidekiq, :qu, :que, :queue_classic)
+ skip unless adapter_is?(:async, :delayed_job, :sidekiq, :que, :queue_classic)
test_job = TestJob.perform_later @id
assert test_job.provider_job_id, "Provider job id should be set by provider"
end
diff --git a/activejob/test/support/integration/adapters/qu.rb b/activejob/test/support/integration/adapters/qu.rb
deleted file mode 100644
index 67db03e279..0000000000
--- a/activejob/test/support/integration/adapters/qu.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module QuJobsManager
- def setup
- require "qu-rails"
- require "qu-redis"
- ActiveJob::Base.queue_adapter = :qu
- ENV["REDISTOGO_URL"] = "redis://127.0.0.1:6379/12"
- backend = Qu::Backend::Redis.new
- backend.namespace = "active_jobs_int_test"
- Qu.backend = backend
- Qu.logger = Rails.logger
- Qu.interval = 0.5
- unless can_run?
- puts "Cannot run integration tests for qu. To be able to run integration tests for qu you need to install and start redis.\n"
- exit
- end
- end
-
- def clear_jobs
- Qu.clear "integration_tests"
- end
-
- def start_workers
- @thread = Thread.new { Qu::Worker.new("integration_tests").start }
- end
-
- def stop_workers
- @thread.kill
- end
-
- def can_run?
- begin
- Qu.backend.connection.client.connect
- rescue
- return false
- end
- true
- end
-end
diff --git a/activemodel/lib/active_model/type/time.rb b/activemodel/lib/active_model/type/time.rb
index ad7ba0351a..c094ee0013 100644
--- a/activemodel/lib/active_model/type/time.rb
+++ b/activemodel/lib/active_model/type/time.rb
@@ -28,14 +28,10 @@ module ActiveModel
private
def cast_value(value)
- return value unless value.is_a?(::String)
+ return apply_seconds_precision(value) unless value.is_a?(::String)
return if value.empty?
- if value.start_with?("2000-01-01")
- dummy_time_value = value
- else
- dummy_time_value = "2000-01-01 #{value}"
- end
+ dummy_time_value = value.sub(/\A(\d\d\d\d-\d\d-\d\d |)/, "2000-01-01 ")
fast_string_to_time(dummy_time_value) || begin
time_hash = ::Date._parse(dummy_time_value)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 92e46ccf9f..aec5fa6ba1 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -130,7 +130,7 @@ module ActiveRecord
end
def quoted_time(value) # :nodoc:
- quoted_date(value).sub(/\A2000-01-01 /, "")
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
end
def quoted_binary(value) # :nodoc:
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index 508132accb..901717ae3d 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -156,7 +156,6 @@ module ActiveRecord
env_config = config[env] if config[env].is_a?(Hash) && !(config[env].key?("adapter") || config[env].key?("url"))
end
- config.reject! { |k, v| v.is_a?(Hash) && !(v.key?("adapter") || v.key?("url")) }
config.merge! env_config if env_config
config.each do |key, value|
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index bfdc7995f0..4c57bd48ab 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -3,7 +3,7 @@
require "active_record/connection_adapters/abstract_mysql_adapter"
require "active_record/connection_adapters/mysql/database_statements"
-gem "mysql2", "~> 0.4.4"
+gem "mysql2", ">= 0.4.4", "< 0.6.0"
require "mysql2"
module ActiveRecord
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 45b230f0f9..e20e5f2914 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -107,7 +107,7 @@ module ActiveRecord
oid = row[4]
comment = row[5]
- using, expressions, where = inddef.scan(/ USING (\w+?) \((.+?)\)(?: WHERE (.+))?\z/).flatten
+ using, expressions, where = inddef.scan(/ USING (\w+?) \((.+?)\)(?: WHERE (.+))?\z/m).flatten
orders = {}
opclasses = {}
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
index 8042dbfea2..70de96326c 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
@@ -17,7 +17,7 @@ module ActiveRecord
end
def quoted_time(value)
- quoted_date(value)
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
end
def quoted_binary(value)
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index 88d28dc52a..ee0e651912 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -57,6 +57,10 @@ module ActiveRecord
spec = resolver.resolve(config).symbolize_keys
spec[:name] = spec_name
+ # use the primary config if a config is not passed in and
+ # it's a three tier config
+ spec = spec[spec_name.to_sym] if spec[spec_name.to_sym]
+
connection_handler.establish_connection(spec)
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index ade5946dd5..6ab80a654d 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -157,6 +157,13 @@ end_warning
end
end
+ initializer "active_record.collection_cache_association_loading" do
+ require "active_record/railties/collection_cache_association_loading"
+ ActiveSupport.on_load(:action_view) do
+ ActionView::PartialRenderer.prepend(ActiveRecord::Railties::CollectionCacheAssociationLoading)
+ end
+ end
+
initializer "active_record.set_reloader_hooks" do
ActiveSupport.on_load(:active_record) do
ActiveSupport::Reloader.before_class_unload do
diff --git a/activerecord/lib/active_record/railties/collection_cache_association_loading.rb b/activerecord/lib/active_record/railties/collection_cache_association_loading.rb
new file mode 100644
index 0000000000..b5129e4239
--- /dev/null
+++ b/activerecord/lib/active_record/railties/collection_cache_association_loading.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module ActiveRecord
+ module Railties # :nodoc:
+ module CollectionCacheAssociationLoading #:nodoc:
+ def setup(context, options, block)
+ @relation = relation_from_options(options)
+
+ super
+ end
+
+ def relation_from_options(cached: nil, partial: nil, collection: nil, **_)
+ return unless cached
+
+ relation = partial if partial.is_a?(ActiveRecord::Relation)
+ relation ||= collection if collection.is_a?(ActiveRecord::Relation)
+
+ if relation && !relation.loaded?
+ relation.skip_preloading!
+ end
+ end
+
+ def collection_without_template
+ @relation.preload_associations(@collection) if @relation
+ super
+ end
+
+ def collection_with_template
+ @relation.preload_associations(@collection) if @relation
+ super
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 736173ae1b..34e643b2de 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -8,7 +8,8 @@ module ActiveRecord
:extending, :unscope]
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
- :reverse_order, :distinct, :create_with, :skip_query_cache]
+ :reverse_order, :distinct, :create_with, :skip_query_cache,
+ :skip_preloading]
CLAUSE_METHODS = [:where, :having, :from]
INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
@@ -546,6 +547,16 @@ module ActiveRecord
ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
end
+ def preload_associations(records)
+ preload = preload_values
+ preload += includes_values unless eager_loading?
+ preloader = nil
+ preload.each do |associations|
+ preloader ||= build_preloader
+ preloader.preload records, associations
+ end
+ end
+
protected
def load_records(records)
@@ -575,13 +586,7 @@ module ActiveRecord
klass.find_by_sql(arel, &block).freeze
end
- preload = preload_values
- preload += includes_values unless eager_loading?
- preloader = nil
- preload.each do |associations|
- preloader ||= build_preloader
- preloader.preload @records, associations
- end
+ preload_associations(@records) unless skip_preloading_value
@records.each(&:readonly!) if readonly_value
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 3afa368575..4e60863e52 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -899,6 +899,11 @@ module ActiveRecord
self
end
+ def skip_preloading! # :nodoc:
+ self.skip_preloading_value = true
+ self
+ end
+
# Returns the Arel object associated with the relation.
def arel(aliases = nil) # :nodoc:
@arel ||= build_arel(aliases)
diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb
index 6dbc977f9a..3290675338 100644
--- a/activerecord/lib/active_record/store.rb
+++ b/activerecord/lib/active_record/store.rb
@@ -17,8 +17,8 @@ module ActiveRecord
# You can set custom coder to encode/decode your serialized attributes to/from different formats.
# JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
#
- # NOTE: If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
- # the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
+ # NOTE: If you are using structured database data types (eg. PostgreSQL +hstore+/+json+, or MySQL 5.7+
+ # +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
# Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
# the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
# using a symbol.
diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
index 6fdb353368..1c85ff5674 100644
--- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
@@ -55,4 +55,11 @@ class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase
assert_equal "'2000-01-01 12:30:00.999999'", @conn.quote(type.serialize(value))
end
+
+ def test_quoted_time_normalizes_date_qualified_time
+ value = ::Time.utc(2018, 3, 11, 12, 30, 0, 999999)
+ type = ActiveRecord::Type::Time.new
+
+ assert_equal "'2000-01-01 12:30:00.999999'", @conn.quote(type.serialize(value))
+ end
end
diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
index f4cc251fb9..c06a4e2c52 100644
--- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb
+++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
@@ -71,6 +71,54 @@ module ActiveRecord
ENV["RAILS_ENV"] = previous_env
end
+ unless in_memory_db?
+ def test_establish_connection_using_3_level_config_defaults_to_default_env_primary_db
+ previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env"
+
+ config = {
+ "default_env" => {
+ "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" },
+ "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" }
+ },
+ "another_env" => {
+ "primary" => { "adapter" => "sqlite3", "database" => "db/another-primary.sqlite3" },
+ "readonly" => { "adapter" => "sqlite3", "database" => "db/another-readonly.sqlite3" }
+ }
+ }
+ @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
+
+ ActiveRecord::Base.establish_connection
+
+ assert_equal "db/primary.sqlite3", ActiveRecord::Base.connection.pool.spec.config[:database]
+ ensure
+ ActiveRecord::Base.configurations = @prev_configs
+ ENV["RAILS_ENV"] = previous_env
+ ActiveRecord::Base.establish_connection(:arunit)
+ end
+
+ def test_establish_connection_using_2_level_config_defaults_to_default_env_primary_db
+ previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env"
+
+ config = {
+ "default_env" => {
+ "adapter" => "sqlite3", "database" => "db/primary.sqlite3"
+ },
+ "another_env" => {
+ "adapter" => "sqlite3", "database" => "db/bad-primary.sqlite3"
+ }
+ }
+ @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
+
+ ActiveRecord::Base.establish_connection
+
+ assert_equal "db/primary.sqlite3", ActiveRecord::Base.connection.pool.spec.config[:database]
+ ensure
+ ActiveRecord::Base.configurations = @prev_configs
+ ENV["RAILS_ENV"] = previous_env
+ ActiveRecord::Base.establish_connection(:arunit)
+ end
+ end
+
def test_establish_connection_using_two_level_configurations
config = { "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } }
@prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config
diff --git a/activerecord/test/cases/date_time_precision_test.rb b/activerecord/test/cases/date_time_precision_test.rb
index 51f6164138..e64a8372d0 100644
--- a/activerecord/test/cases/date_time_precision_test.rb
+++ b/activerecord/test/cases/date_time_precision_test.rb
@@ -27,6 +27,24 @@ if subsecond_precision_supported?
assert_equal 5, Foo.columns_hash["updated_at"].precision
end
+ def test_datetime_precision_is_truncated_on_assignment
+ @connection.create_table(:foos, force: true)
+ @connection.add_column :foos, :created_at, :datetime, precision: 0
+ @connection.add_column :foos, :updated_at, :datetime, precision: 6
+
+ time = ::Time.now.change(nsec: 123456789)
+ foo = Foo.new(created_at: time, updated_at: time)
+
+ assert_equal 0, foo.created_at.nsec
+ assert_equal 123456000, foo.updated_at.nsec
+
+ foo.save!
+ foo.reload
+
+ assert_equal 0, foo.created_at.nsec
+ assert_equal 123456000, foo.updated_at.nsec
+ end
+
def test_timestamps_helper_with_custom_precision
@connection.create_table(:foos, force: true) do |t|
t.timestamps precision: 4
diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb
index 6534770c57..92eb0c814f 100644
--- a/activerecord/test/cases/quoting_test.rb
+++ b/activerecord/test/cases/quoting_test.rb
@@ -46,27 +46,60 @@ module ActiveRecord
assert_equal t.to_s(:db), @quoter.quoted_date(t)
end
- def test_quoted_time_utc
+ def test_quoted_timestamp_utc
with_timezone_config default: :utc do
t = Time.now.change(usec: 0)
assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t)
end
end
- def test_quoted_time_local
+ def test_quoted_timestamp_local
with_timezone_config default: :local do
t = Time.now.change(usec: 0)
assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t)
end
end
- def test_quoted_time_crazy
+ def test_quoted_timestamp_crazy
with_timezone_config default: :asdfasdf do
t = Time.now.change(usec: 0)
assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t)
end
end
+ def test_quoted_time_utc
+ with_timezone_config default: :utc do
+ t = Time.now.change(usec: 0)
+
+ expected = t.getutc.change(year: 2000, month: 1, day: 1)
+ expected = expected.to_s(:db).sub("2000-01-01 ", "")
+
+ assert_equal expected, @quoter.quoted_time(t)
+ end
+ end
+
+ def test_quoted_time_local
+ with_timezone_config default: :local do
+ t = Time.now.change(usec: 0)
+
+ expected = t.change(year: 2000, month: 1, day: 1)
+ expected = expected.getlocal.to_s(:db).sub("2000-01-01 ", "")
+
+ assert_equal expected, @quoter.quoted_time(t)
+ end
+ end
+
+ def test_quoted_time_crazy
+ with_timezone_config default: :asdfasdf do
+ t = Time.now.change(usec: 0)
+
+ expected = t.change(year: 2000, month: 1, day: 1)
+ expected = expected.getlocal.to_s(:db).sub("2000-01-01 ", "")
+
+ assert_equal expected, @quoter.quoted_time(t)
+ end
+ end
+
def test_quoted_datetime_utc
with_timezone_config default: :utc do
t = Time.now.change(usec: 0).to_datetime
diff --git a/activerecord/test/cases/relation/mutation_test.rb b/activerecord/test/cases/relation/mutation_test.rb
index 1428b3e132..d6351bfe88 100644
--- a/activerecord/test/cases/relation/mutation_test.rb
+++ b/activerecord/test/cases/relation/mutation_test.rb
@@ -59,7 +59,7 @@ module ActiveRecord
assert_equal [], relation.extending_values
end
- (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with, :skip_query_cache]).each do |method|
+ (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with, :skip_query_cache, :skip_preloading]).each do |method|
test "##{method}!" do
assert relation.public_send("#{method}!", :foo).equal?(relation)
assert_equal :foo, relation.public_send("#{method}_value")
@@ -137,6 +137,11 @@ module ActiveRecord
assert relation.skip_query_cache_value
end
+ test "skip_preloading!" do
+ relation.skip_preloading!
+ assert relation.skip_preloading_value
+ end
+
private
def relation
@relation ||= Relation.new(FakeKlass)
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index a612ce9bb2..50d766a99e 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -298,7 +298,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
def test_schema_dump_expression_indices
index_definition = dump_table_schema("companies").split(/\n/).grep(/t\.index.*company_expression_index/).first.strip
- assert_equal 't.index "lower((name)::text)", name: "company_expression_index"', index_definition
+ assert_match %r{CASE.+lower\(\(name\)::text\)}i, index_definition
end
def test_schema_dump_interval_type
diff --git a/activerecord/test/cases/time_precision_test.rb b/activerecord/test/cases/time_precision_test.rb
index 41455637bb..086500de38 100644
--- a/activerecord/test/cases/time_precision_test.rb
+++ b/activerecord/test/cases/time_precision_test.rb
@@ -27,6 +27,24 @@ if subsecond_precision_supported?
assert_equal 6, Foo.columns_hash["finish"].precision
end
+ def test_time_precision_is_truncated_on_assignment
+ @connection.create_table(:foos, force: true)
+ @connection.add_column :foos, :start, :time, precision: 0
+ @connection.add_column :foos, :finish, :time, precision: 6
+
+ time = ::Time.now.change(nsec: 123456789)
+ foo = Foo.new(start: time, finish: time)
+
+ assert_equal 0, foo.start.nsec
+ assert_equal 123456000, foo.finish.nsec
+
+ foo.save!
+ foo.reload
+
+ assert_equal 0, foo.start.nsec
+ assert_equal 123456000, foo.finish.nsec
+ end
+
def test_passing_precision_to_time_does_not_set_limit
@connection.create_table(:foos, force: true) do |t|
t.time :start, precision: 3
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 8b0106dbf0..ca86100bc5 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -210,7 +210,7 @@ ActiveRecord::Schema.define do
t.index [:firm_id, :type, :rating], name: "company_index", length: { type: 10 }, order: { rating: :desc }
t.index [:firm_id, :type], name: "company_partial_index", where: "(rating > 10)"
t.index :name, name: "company_name_index", using: :btree
- t.index "lower(name)", name: "company_expression_index" if supports_expression_index?
+ t.index "(CASE WHEN rating > 0 THEN lower(name) END)", name: "company_expression_index" if supports_expression_index?
end
create_table :content, force: true do |t|
diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb
index 8ab7a44131..5e489f4be1 100644
--- a/activestorage/lib/active_storage/service/s3_service.rb
+++ b/activestorage/lib/active_storage/service/s3_service.rb
@@ -9,8 +9,8 @@ module ActiveStorage
class Service::S3Service < Service
attr_reader :client, :bucket, :upload_options
- def initialize(access_key_id:, secret_access_key:, region:, bucket:, upload: {}, **options)
- @client = Aws::S3::Resource.new(access_key_id: access_key_id, secret_access_key: secret_access_key, region: region, **options)
+ def initialize(bucket:, upload: {}, **options)
+ @client = Aws::S3::Resource.new(**options)
@bucket = @client.bucket(bucket)
@upload_options = upload
diff --git a/activestorage/test/service/s3_service_test.rb b/activestorage/test/service/s3_service_test.rb
index d6996209d2..7833e51122 100644
--- a/activestorage/test/service/s3_service_test.rb
+++ b/activestorage/test/service/s3_service_test.rb
@@ -3,7 +3,7 @@
require "service/shared_service_tests"
require "net/http"
-if SERVICE_CONFIGURATIONS[:s3] && SERVICE_CONFIGURATIONS[:s3][:access_key_id].present?
+if SERVICE_CONFIGURATIONS[:s3]
class ActiveStorage::Service::S3ServiceTest < ActiveSupport::TestCase
SERVICE = ActiveStorage::Service.configure(:s3, SERVICE_CONFIGURATIONS)
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 1ea2d0bbf2..6967c164ab 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -714,11 +714,9 @@ module ActiveSupport
# Creates a new cache entry for the specified value. Options supported are
# +:compress+, +:compress_threshold+, and +:expires_in+.
def initialize(value, options = {})
- if should_compress?(value, options)
- @value = compress(value)
- @compressed = true
- else
- @value = value
+ @value = value
+ if should_compress?(options)
+ compress!
end
@version = options[:version]
@@ -783,28 +781,31 @@ module ActiveSupport
end
private
- def should_compress?(value, options)
- if value && options.fetch(:compress, true)
+ def should_compress?(options)
+ if @value && options.fetch(:compress, true)
compress_threshold = options.fetch(:compress_threshold, DEFAULT_COMPRESS_LIMIT)
- serialized_value_size = (value.is_a?(String) ? value : Marshal.dump(value)).bytesize
+ serialized_value_size = (@value.is_a?(String) ? @value : marshaled_value).bytesize
- return true if serialized_value_size >= compress_threshold
+ serialized_value_size >= compress_threshold
end
-
- false
end
def compressed?
defined?(@compressed) ? @compressed : false
end
- def compress(value)
- Zlib::Deflate.deflate(Marshal.dump(value))
+ def compress!
+ @value = Zlib::Deflate.deflate(marshaled_value)
+ @compressed = true
end
def uncompress(value)
Marshal.load(Zlib::Inflate.inflate(value))
end
+
+ def marshaled_value
+ @marshaled_value ||= Marshal.dump(@value)
+ end
end
end
end
diff --git a/activesupport/lib/active_support/cache/redis_cache_store.rb b/activesupport/lib/active_support/cache/redis_cache_store.rb
index a134bb7095..a1cb6db25d 100644
--- a/activesupport/lib/active_support/cache/redis_cache_store.rb
+++ b/activesupport/lib/active_support/cache/redis_cache_store.rb
@@ -154,7 +154,7 @@ module ActiveSupport
# :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
#
# No namespace is set by default. Provide one if the Redis cache
- # server is shared with other apps: <tt>namespace: 'myapp-cache'<tt>.
+ # server is shared with other apps: <tt>namespace: 'myapp-cache'</tt>.
#
# Compression is enabled by default with a 1kB threshold, so cached
# values larger than 1kB are automatically compressed. Disable by
diff --git a/guides/source/5_2_release_notes.md b/guides/source/5_2_release_notes.md
index 3c36ba5f7a..541c025fac 100644
--- a/guides/source/5_2_release_notes.md
+++ b/guides/source/5_2_release_notes.md
@@ -85,69 +85,9 @@ Rails 5.2 ships with a new DSL that allows you to configure a
for your application. You can configure a global default policy and then
override it on a per-resource basis and even use lambdas to inject per-request
values into the header such as account subdomains in a multi-tenant application.
-
-Example global policy:
-
-```ruby
-# config/initializers/content_security_policy.rb
-Rails.application.config.content_security_policy do |policy|
- policy.default_src :self, :https
- policy.font_src :self, :https, :data
- policy.img_src :self, :https, :data
- policy.object_src :none
- policy.script_src :self, :https
- policy.style_src :self, :https
-
- # Specify URI for violation reports
- policy.report_uri "/csp-violation-report-endpoint"
-end
-```
-
-Example controller overrides:
-
-```ruby
-# Override policy inline
-class PostsController < ApplicationController
- content_security_policy do |p|
- p.upgrade_insecure_requests true
- end
-end
-
-# Using literal values
-class PostsController < ApplicationController
- content_security_policy do |p|
- p.base_uri "https://www.example.com"
- end
-end
-
-# Using mixed static and dynamic values
-class PostsController < ApplicationController
- content_security_policy do |p|
- p.base_uri :self, -> { "https://#{current_user.domain}.example.com" }
- end
-end
-
-# Disabling the global CSP
-class LegacyPagesController < ApplicationController
- content_security_policy false, only: :index
-end
-```
-
-To report only content violations for migrating
-legacy content using the `content_security_policy_report_only`
-configuration attribute:
-
-```ruby
-# config/initializers/content_security_policy.rb
-Rails.application.config.content_security_policy_report_only = true
-```
-
-```ruby
-# Controller override
-class PostsController < ApplicationController
- content_security_policy_report_only only: :index
-end
-```
+You can read more about this in the
+[Securing Rails Applications](security.html#content-security-policy)
+guide.
Railties
--------
@@ -172,26 +112,16 @@ Please refer to the [Changelog][railties] for detailed changes.
### Notable changes
-* Namespace error pages' CSS selectors to stop the styles from bleeding
- into other pages when using Turbolinks.
- ([Pull Request](https://github.com/rails/rails/pull/28814))
-
* Added a shared section to `config/database.yml` that will be loaded for
all environments.
([Pull Request](https://github.com/rails/rails/pull/28896))
-* Allow irb options to be passed from `rails console` command.
- ([Pull Request](https://github.com/rails/rails/pull/29010))
-
* Add `railtie.rb` to the plugin generator.
([Pull Request](https://github.com/rails/rails/pull/29576))
* Clear screenshot files in `tmp:clear` task.
([Pull Request](https://github.com/rails/rails/pull/29534))
-* Load environment file in `dbconsole` command.
- ([Pull Request](https://github.com/rails/rails/pull/29725))
-
* Skip unused components when running `bin/rails app:update`.
If the initial app generation skipped Action Cable, Active Record etc.,
the update task honors those skips too.
@@ -246,19 +176,11 @@ Please refer to the [Changelog][railties] for detailed changes.
* Add `mini_magick` to default `Gemfile` as comment.
([Pull Request](https://github.com/rails/rails/pull/30633))
-* Gemfile for new apps: upgrade redis-rb from ~> 3.0 to 4.0.
- ([Pull Request](https://github.com/rails/rails/pull/30748))
-
* `rails new` and `rails plugin new` get `Active Storage` by default.
Add ability to skip `Active Storage` with `--skip-active-storage`
and do so automatically when `--skip-active-record` is used.
([Pull Request](https://github.com/rails/rails/pull/30101))
-* Fix minitest rails plugin.
- The custom reporters are added only if needed.
- This will fix conflicts with others plugins.
- ([Commit](https://github.com/rails/rails/commit/ac99916fcf7bf27bb1519d4f7387c6b4c5f0463d))
-
Action Cable
------------
@@ -277,9 +199,6 @@ Please refer to the [Changelog][action-cable] for detailed changes.
* Hash long stream identifiers when using PostgreSQL adapter.
([Pull Request](https://github.com/rails/rails/pull/29297))
-* Add support for compatibility with redis-rb gem for 4.0 version.
- ([Pull Request](https://github.com/rails/rails/pull/30748))
-
Action Pack
-----------
@@ -298,10 +217,6 @@ Please refer to the [Changelog][action-pack] for detailed changes.
### Notable changes
-* Add `action_controller_api` and `action_controller_base` load hooks to be
- called in `ActiveSupport.on_load`.
- ([Pull Request](https://github.com/rails/rails/pull/28402))
-
* Add support for recyclable cache keys with fragment caching.
([Pull Request](https://github.com/rails/rails/pull/29092))
@@ -312,18 +227,9 @@ Please refer to the [Changelog][action-pack] for detailed changes.
* AEAD encrypted cookies and sessions with GCM.
([Pull Request](https://github.com/rails/rails/pull/28132))
-* `driven_by` now registers poltergeist and capybara-webkit.
- ([Pull Request](https://github.com/rails/rails/pull/29315))
-
-* Fallback `ActionController::Parameters#to_s` to `Hash#to_s`.
- ([Pull Request](https://github.com/rails/rails/pull/29630))
-
* Protect from forgery by default.
([Pull Request](https://github.com/rails/rails/pull/29742))
-* Make `take_failed_screenshot` work within engine.
- ([Pull Request](https://github.com/rails/rails/pull/30421))
-
* Enforce signed/encrypted cookie expiry server side.
([Pull Request](https://github.com/rails/rails/pull/30121))
@@ -353,9 +259,6 @@ Please refer to the [Changelog][action-pack] for detailed changes.
[Commit](https://github.com/rails/rails/commit/619b1b6353a65e1635d10b8f8c6630723a5a6f1a),
[Commit](https://github.com/rails/rails/commit/4ec8bf68ff92f35e79232fbd605012ce1f4e1e6e))
-* Fix optimized url helpers when using relative url root.
- ([Pull Request](https://github.com/rails/rails/pull/31261))
-
* Register most popular audio/video/font mime types supported by modern
browsers.
([Pull Request](https://github.com/rails/rails/pull/31251))
@@ -409,21 +312,10 @@ Please refer to the [Changelog][action-view] for detailed changes.
### Notable changes
-* Update `distance_of_time_in_words` helper to display better error messages
- for bad input.
- ([Pull Request](https://github.com/rails/rails/pull/20701))
-
* Add `:json` type to `auto_discovery_link_tag` to support
[JSON Feeds](https://jsonfeed.org/version/1).
([Pull Request](https://github.com/rails/rails/pull/29158))
-* Generate field ids in `collection_check_boxes` and
- `collection_radio_buttons`.
- ([Pull Request](https://github.com/rails/rails/pull/29412))
-
-* Fix issues with scopes and engine on `current_page?` method.
- ([Pull Request](https://github.com/rails/rails/pull/29503))
-
* Add `srcset` option to `image_tag` helper.
([Pull Request](https://github.com/rails/rails/pull/29349))
@@ -453,10 +345,6 @@ Please refer to the [Changelog][action-mailer] for detailed changes.
* Add `assert_enqueued_email_with` test helper.
([Pull Request](https://github.com/rails/rails/pull/30695))
-* Bring back proc with arity of 1 in `ActionMailer::Base.default` proc
- since it was supported in Rails 5.0 but not deprecated.
- ([Pull Request](https://github.com/rails/rails/pull/30391))
-
Active Record
-------------
@@ -546,9 +434,6 @@ Please refer to the [Changelog][active-record] for detailed changes.
when the current migration does not exist.
([Commit](https://github.com/rails/rails/commit/bb9d6eb094f29bb94ef1f26aa44f145f17b973fe))
-* Add type caster to `RuntimeReflection#alias_name`.
- ([Pull Request](https://github.com/rails/rails/pull/28961))
-
* Respect `SchemaDumper.ignore_tables` in rake tasks for
databases structure dump.
([Pull Request](https://github.com/rails/rails/pull/29077))
@@ -559,39 +444,16 @@ Please refer to the [Changelog][active-record] for detailed changes.
does not include a timestamp any more.
([Pull Request](https://github.com/rails/rails/pull/29092))
-* Loading model schema from database is now thread-safe.
- ([Pull Request](https://github.com/rails/rails/pull/29216))
-
* Prevent creation of bind param if casted value is nil.
([Pull Request](https://github.com/rails/rails/pull/29282))
* Use bulk INSERT to insert fixtures for better performance.
([Pull Request](https://github.com/rails/rails/pull/29504))
-* Fix destroying existing object does not work well when optimistic locking
- enabled and `locking_column` is null in the database.
- ([Pull Request](https://github.com/rails/rails/pull/28926))
-
-* `ActiveRecord::Persistence#touch` does not work well
- when optimistic locking enabled and `locking_column`,
- without default value, is null in the database.
- ([Pull Request](https://github.com/rails/rails/pull/28914))
-
* Merging two relations representing nested joins no longer transforms
the joins of the merged relation into LEFT OUTER JOIN.
([Pull Request](https://github.com/rails/rails/pull/27063))
-* Previously, when building records using a `has_many :through` association,
- if the child records were deleted before the parent was saved,
- they would still be persisted. Now, if child records are deleted
- before the parent is saved on a `has_many :through` association,
- the child records will not be persisted.
- ([Pull Request](https://github.com/rails/rails/pull/29593))
-
-* Query cache was unavailable when entering the `ActiveRecord::Base.cache`
- block without being connected.
- ([Pull Request](https://github.com/rails/rails/pull/29609))
-
* Fix transactions to apply state to child transactions.
Previously, if you had a nested transaction and the outer transaction was
rolledback, the record from the inner transaction would still be marked
@@ -617,26 +479,10 @@ Please refer to the [Changelog][active-record] for detailed changes.
recognize 't' and 'f' as was previously serialized.
([Pull Request](https://github.com/rails/rails/pull/29699))
-* `Relation#joins` is no longer affected by the target model's
- `current_scope`, with the exception of `unscoped`.
- ([Commit](https://github.com/rails/rails/commit/5c71000d086cc42516934415b79380c2224e1614))
-
* Values constructed using multi-parameter assignment will now use the
post-type-cast value for rendering in single-field form inputs.
([Commit](https://github.com/rails/rails/commit/1519e976b224871c7f7dd476351930d5d0d7faf6))
-* Fix `unscoped(where: [columns])` removing the wrong bind values.
- ([Pull Request](https://github.com/rails/rails/pull/29780))
-
-* When a `has_one` association is destroyed by `dependent: destroy`,
- `destroyed_by_association` will now be set to the reflection, matching the
- behaviour of `has_many` associations.
- ([Pull Request](https://github.com/rails/rails/pull/29855))
-
-* Fix `COUNT(DISTINCT ...)` with `ORDER BY` and `LIMIT`
- to keep the existing select list.
- ([Pull Request](https://github.com/rails/rails/pull/29848))
-
* `ApplicationRecord` is no longer generated when generating models. If you
need to generate it, it can be created with `rails g application_record`.
([Pull Request](https://github.com/rails/rails/pull/29916))
@@ -652,9 +498,6 @@ Please refer to the [Changelog][active-record] for detailed changes.
* Add `binary` fixture helper method.
([Pull Request](https://github.com/rails/rails/pull/30073))
-* Ensure `sum` honors `distinct` on `has_many :through` associations.
- ([Commit](https://github.com/rails/rails/commit/566f1fd068711dfe557bef63406f8dd6d41d473d))
-
* Automatically guess the inverse associations for STI.
([Pull Request](https://github.com/rails/rails/pull/23425))
@@ -676,19 +519,6 @@ Please refer to the [Changelog][active-record] for detailed changes.
* PostgreSQL `tsrange` now preserves subsecond precision.
([Pull Request](https://github.com/rails/rails/pull/30725))
-* Fix `COUNT(DISTINCT ...)` for `GROUP BY` with `ORDER BY` and `LIMIT`.
- ([Commit](https://github.com/rails/rails/commit/5668dc6b1863ef43be8f8ef0fb1d5db913085fb3))
-
-* MySQL: Don't lose `auto_increment: true` in the `db/schema.rb`.
- ([Commit](https://github.com/rails/rails/commit/9493d4553569118b2a85da84fd3a8ba2b5b2de76))
-
-* Fix longer sequence name detection for serial columns.
- ([Pull Request](https://github.com/rails/rails/pull/28339))
-
-* Fix `bin/rails db:setup` and `bin/rails db:test:prepare` create wrong
- ar_internal_metadata's data for a test database.
- ([Pull Request](https://github.com/rails/rails/pull/30579))
-
* Raises when calling `lock!` in a dirty record.
([Commit](https://github.com/rails/rails/commit/63cf15877bae859ff7b4ebaf05186f3ca79c1863))
@@ -732,9 +562,6 @@ Please refer to the [Changelog][active-record] for detailed changes.
* Add support for PostgreSQL operator classes to `add_index`.
([Pull Request](https://github.com/rails/rails/pull/19090))
-* Fix conflicts `counter_cache` with `touch: true` by optimistic locking.
- ([Pull Request](https://github.com/rails/rails/pull/31405))
-
* Log database query callers.
([Pull Request](https://github.com/rails/rails/pull/26815),
[Pull Request](https://github.com/rails/rails/pull/31519),
@@ -746,16 +573,6 @@ Please refer to the [Changelog][active-record] for detailed changes.
* Using subselect for `delete_all` with `limit` or `offset`.
([Commit](https://github.com/rails/rails/commit/9e7260da1bdc0770cf4ac547120c85ab93ff3d48))
-* Fix `count(:all)` to correctly work `distinct` with custom SELECT list.
- ([Commit](https://github.com/rails/rails/commit/c6cd9a59f200863ccfe8ad1d9c5a8876c39b9c5c))
-
-* Fix to invoke callbacks when using `update_attribute`.
- ([Commit](https://github.com/rails/rails/commit/732aa34b6e6459ad66a3d3ad107cfff75cc45160))
-
-* Use `count(:all)` in `HasManyAssociation#count_records` to prevent invalid
- SQL queries for association counting.
- ([Pull Request](https://github.com/rails/rails/pull/27561))
-
* Fixed inconsistency with `first(n)` when used with `limit()`.
The `first(n)` finder now respects the `limit()`, making it consistent
with `relation.to_a.first(n)`, and also with the behavior of `last(n)`.
@@ -779,17 +596,10 @@ Please refer to the [Changelog][active-record] for detailed changes.
* Clear the transaction state when an Active Record object is duped.
([Pull Request](https://github.com/rails/rails/pull/31751))
-* Fix `count(:all)` with eager loading and having an order other than
- the driving table.
- ([Commit](https://github.com/rails/rails/commit/ebc09ed9ad9a04338138739226a1a92c7a2707ee))
-
* Fix not expanded problem when passing an Array object as argument
to the where method using `composed_of` column.
([Pull Request](https://github.com/rails/rails/pull/31724))
-* PostgreSQL: Allow pg-1.0 gem to be used with Active Record.
- ([Pull Request](https://github.com/rails/rails/pull/31671))
-
* Make `reflection.klass` raise if `polymorphic?` not to be misused.
([Commit](https://github.com/rails/rails/commit/63fc1100ce054e3e11c04a547cdb9387cd79571a))
@@ -798,10 +608,6 @@ Please refer to the [Changelog][active-record] for detailed changes.
even if `ORDER BY` columns include other table's primary key.
([Commit](https://github.com/rails/rails/commit/851618c15750979a75635530200665b543561a44))
-* Fix that after commit callbacks on update does not triggered
- when optimistic locking is enabled.
- ([Commit](https://github.com/rails/rails/commit/7f9bd034c485c2425ae0164ff5d6374834e3aa1d))
-
* Fix `dependent: :destroy` issue for has_one/belongs_to relationship where
the parent class was getting deleted when the child was not.
([Commit](https://github.com/rails/rails/commit/b0fc04aa3af338d5a90608bf37248668d59fc881))
@@ -818,10 +624,6 @@ Please refer to the [Changelog][active-model] for detailed changes.
Change `#values` to only return the not empty values.
([Pull Request](https://github.com/rails/rails/pull/28584))
-* Fix regression in numericality validator when comparing Decimal and Float
- input values with more scale than the schema.
- ([Pull Request](https://github.com/rails/rails/pull/28584))
-
* Add method `#merge!` for `ActiveModel::Errors`.
([Pull Request](https://github.com/rails/rails/pull/29714))
@@ -832,9 +634,6 @@ Please refer to the [Changelog][active-model] for detailed changes.
is `false`.
([Pull Request](https://github.com/rails/rails/pull/31058))
-* Fix to working before/after validation callbacks on multiple contexts.
- ([Pull Request](https://github.com/rails/rails/pull/31483))
-
* Models using the attributes API with a proc default can now be marshalled.
([Commit](https://github.com/rails/rails/commit/0af36c62a5710e023402e37b019ad9982e69de4b))
@@ -883,10 +682,6 @@ Please refer to the [Changelog][active-support] for detailed changes.
in Active Record and its use in Action Pack's fragment caching.
([Pull Request](https://github.com/rails/rails/pull/29092))
-* Fix implicit coercion calculations with scalars and durations.
- ([Pull Request](https://github.com/rails/rails/pull/29163),
- [Pull Request](https://github.com/rails/rails/pull/29971))
-
* Add `ActiveSupport::CurrentAttributes` to provide a thread-isolated
attributes singleton. Primary use case is keeping all the per-request
attributes easily available to the whole system.
@@ -923,9 +718,6 @@ Please refer to the [Changelog][active-support] for detailed changes.
`ActiveSupport::MessageEncryptor`.
([Pull Request](https://github.com/rails/rails/pull/29892))
-* Fix modulo operations involving durations.
- ([Commit](https://github.com/rails/rails/commit/a54e13bd2e8fb4d6aa0aebe59271699a2d62567b))
-
* Update `String#camelize` to provide feedback when wrong option is passed.
([Pull Request](https://github.com/rails/rails/pull/30039))
@@ -1016,9 +808,6 @@ Please refer to the [Changelog][active-support] for detailed changes.
This allows to specify multiple numeric differences in the same assertion.
([Pull Request](https://github.com/rails/rails/pull/31600))
-* Return all mappings for a timezone identifier in `country_zones`.
- ([Commit](https://github.com/rails/rails/commit/cdce6a709e1cbc98fff009effc3b1b3ce4c7e8db))
-
* Caching: MemCache and Redis `read_multi` and `fetch_multi` speedup.
Read from the local in-memory cache before consulting the backend.
([Commit](https://github.com/rails/rails/commit/a2b97e4ffef971607a1be8fc7909f099b6840f36))
@@ -1030,9 +819,6 @@ Please refer to the [Changelog][active-job] for detailed changes.
### Notable changes
-* Add support for compatibility with redis-rb gem for 4.0 version.
- ([Pull Request](https://github.com/rails/rails/pull/30748))
-
* Allow block to be passed to `ActiveJob::Base.discard_on` to allow custom
handling of discard jobs.
([Pull Request](https://github.com/rails/rails/pull/30622))
diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md
index 9d911d4ee4..6d52ac0a99 100644
--- a/guides/source/active_job_basics.md
+++ b/guides/source/active_job_basics.md
@@ -147,7 +147,7 @@ class GuestsCleanupJob < ApplicationJob
#....
end
-# Now your job will use `resque` as it's backend queue adapter overriding what
+# Now your job will use `resque` as its backend queue adapter overriding what
# was configured in `config.active_job.queue_adapter`.
```
diff --git a/guides/source/active_storage_overview.md b/guides/source/active_storage_overview.md
index 831a02a9a1..d67f65e88a 100644
--- a/guides/source/active_storage_overview.md
+++ b/guides/source/active_storage_overview.md
@@ -114,6 +114,13 @@ gem "aws-sdk-s3", require: false
NOTE: The core features of Active Storage require the following permissions: `s3:ListBucket`, `s3:PutObject`, `s3:GetObject`, and `s3:DeleteObject`. If you have additional upload options configured such as setting ACLs then additional permissions may be required.
+NOTE: If you want to use environment variables, standard SDK configuration files, profiles,
+IAM instance profiles or task roles, you can omit the `access_key_id`, `secret_access_key`,
+and `region` keys in the example above. The Amazon S3 Service supports all of the
+authentication options described in the [AWS SDK documentation]
+(https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html).
+
+
### Microsoft Azure Storage Service
Declare an Azure Storage service in `config/storage.yml`:
diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md
index 5dde6f34fa..3f357b532b 100644
--- a/guides/source/caching_with_rails.md
+++ b/guides/source/caching_with_rails.md
@@ -446,30 +446,28 @@ config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.c
### ActiveSupport::Cache::RedisCacheStore
-The Redis cache store takes advantage of Redis support for least-recently-used
-and least-frequently-used key eviction when it reaches max memory, allowing it
-to behave much like a Memcached cache server.
+The Redis cache store takes advantage of Redis support for automatic eviction
+when it reaches max memory, allowing it to behave much like a Memcached cache server.
Deployment note: Redis doesn't expire keys by default, so take care to use a
dedicated Redis cache server. Don't fill up your persistent-Redis server with
volatile cache data! Read the
[Redis cache server setup guide](https://redis.io/topics/lru-cache) in detail.
-For an all-cache Redis server, set `maxmemory-policy` to an `allkeys` policy.
-Redis 4+ support least-frequently-used (`allkeys-lfu`) eviction, an excellent
-default choice. Redis 3 and earlier should use `allkeys-lru` for
-least-recently-used eviction.
+For a cache-only Redis server, set `maxmemory-policy` to one of the variants of allkeys.
+Redis 4+ supports least-frequently-used eviction (`allkeys-lfu`), an excellent
+default choice. Redis 3 and earlier should use least-recently-used eviction (`allkeys-lru`).
Set cache read and write timeouts relatively low. Regenerating a cached value
is often faster than waiting more than a second to retrieve it. Both read and
write timeouts default to 1 second, but may be set lower if your network is
-consistently low latency.
+consistently low-latency.
By default, the cache store will not attempt to reconnect to Redis if the
connection fails during a request. If you experience frequent disconnects you
may wish to enable reconnect attempts.
-Cache reads and writes never raise exceptions. They just return `nil` instead,
+Cache reads and writes never raise exceptions; they just return `nil` instead,
behaving as if there was nothing in the cache. To gauge whether your cache is
hitting exceptions, you may provide an `error_handler` to report to an
exception gathering service. It must accept three keyword arguments: `method`,
@@ -477,12 +475,33 @@ the cache store method that was originally called; `returning`, the value that
was returned to the user, typically `nil`; and `exception`, the exception that
was rescued.
-Putting it all together, a production Redis cache store may look something
-like this:
+To get started, add the redis gem to your Gemfile:
```ruby
-cache_servers = %w[ "redis://cache-01:6379/0", "redis://cache-02:6379/0", … ],
-config.cache_store = :redis_cache_store, url: cache_servers,
+gem 'redis'
+```
+
+You can enable support for the faster [hiredis](https://github.com/redis/hiredis)
+connection library by additionally adding its ruby wrapper to your Gemfile:
+
+```ruby
+gem 'hiredis'
+```
+
+Redis cache store will automatically require & use hiredis if available. No further
+configuration is needed.
+
+Finally, add the configuration in the relevant `config/environments/*.rb` file:
+
+```ruby
+config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'] }
+```
+
+A more complex, production Redis cache store may look something like this:
+
+```ruby
+cache_servers = %w(redis://cache-01:6379/0 redis://cache-02:6379/0)
+config.cache_store = :redis_cache_store, { url: cache_servers,
connect_timeout: 30, # Defaults to 20 seconds
read_timeout: 0.2, # Defaults to 1 second
@@ -491,9 +510,10 @@ config.cache_store = :redis_cache_store, url: cache_servers,
error_handler: -> (method:, returning:, exception:) {
# Report errors to Sentry as warnings
- Raven.capture_exception exception, level: 'warning",
+ Raven.capture_exception exception, level: 'warning',
tags: { method: method, returning: returning }
}
+}
```
### ActiveSupport::Cache::NullStore
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index f545b90103..5b6cfe6659 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -1125,7 +1125,7 @@ TIP: Rails automatically wraps fields that contain an error with a div
with class `field_with_errors`. You can define a CSS rule to make them
standout.
-Now you'll get a nice error message when saving an article without title when
+Now you'll get a nice error message when saving an article without a title when
you attempt to do just that on the new article form
<http://localhost:3000/articles/new>:
@@ -1522,7 +1522,7 @@ comments on articles.
### Generating a Model
We're going to see the same generator that we used before when creating
-the `Article` model. This time we'll create a `Comment` model to hold
+the `Article` model. This time we'll create a `Comment` model to hold a
reference to an article. Run this command in your terminal:
```bash
@@ -1857,7 +1857,7 @@ This will now render the partial in `app/views/comments/_comment.html.erb` once
for each comment that is in the `@article.comments` collection. As the `render`
method iterates over the `@article.comments` collection, it assigns each
comment to a local variable named the same as the partial, in this case
-`comment` which is then available in the partial for us to show.
+`comment`, which is then available in the partial for us to show.
### Rendering a Partial Form
@@ -2060,7 +2060,7 @@ What's Next?
Now that you've seen your first Rails application, you should feel free to
update it and experiment on your own.
-Remember you don't have to do everything without help. As you need assistance
+Remember, you don't have to do everything without help. As you need assistance
getting up and running with Rails, feel free to consult these support
resources:
diff --git a/guides/source/security.md b/guides/source/security.md
index 4cf6c06f2d..b419f7b48d 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -1089,6 +1089,112 @@ Here is a list of common headers:
* **Access-Control-Allow-Origin:** Used to control which sites are allowed to bypass same origin policies and send cross-origin requests.
* **Strict-Transport-Security:** [Used to control if the browser is allowed to only access a site over a secure connection](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security)
+### Content Security Policy
+
+Rails provides a DSL that allows you to configure a
+[Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
+for your application. You can configure a global default policy and then
+override it on a per-resource basis and even use lambdas to inject per-request
+values into the header such as account subdomains in a multi-tenant application.
+
+Example global policy:
+
+```ruby
+# config/initializers/content_security_policy.rb
+Rails.application.config.content_security_policy do |policy|
+ policy.default_src :self, :https
+ policy.font_src :self, :https, :data
+ policy.img_src :self, :https, :data
+ policy.object_src :none
+ policy.script_src :self, :https
+ policy.style_src :self, :https
+
+ # Specify URI for violation reports
+ policy.report_uri "/csp-violation-report-endpoint"
+end
+```
+
+Example controller overrides:
+
+```ruby
+# Override policy inline
+class PostsController < ApplicationController
+ content_security_policy do |p|
+ p.upgrade_insecure_requests true
+ end
+end
+
+# Using literal values
+class PostsController < ApplicationController
+ content_security_policy do |p|
+ p.base_uri "https://www.example.com"
+ end
+end
+
+# Using mixed static and dynamic values
+class PostsController < ApplicationController
+ content_security_policy do |p|
+ p.base_uri :self, -> { "https://#{current_user.domain}.example.com" }
+ end
+end
+
+# Disabling the global CSP
+class LegacyPagesController < ApplicationController
+ content_security_policy false, only: :index
+end
+```
+
+Use the `content_security_policy_report_only`
+configuration attribute to set
+[Content-Security-Policy-Report-Only](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only)
+in order to report only content violations for migrating
+legacy content
+
+```ruby
+# config/initializers/content_security_policy.rb
+Rails.application.config.content_security_policy_report_only = true
+```
+
+```ruby
+# Controller override
+class PostsController < ApplicationController
+ content_security_policy_report_only only: :index
+end
+```
+
+You can enable automatic nonce generation:
+
+```ruby
+# config/initializers/content_security_policy.rb
+Rails.application.config.content_security_policy do |policy|
+ policy.script_src :self, :https
+end
+
+Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
+```
+
+Then you can add an automatic nonce value by passing `nonce: true`
+as part of `html_options`. Example:
+
+```html+erb
+<%= javascript_tag nonce: true do -%>
+ alert('Hello, World!');
+<% end -%>
+```
+
+Use [`csp_meta_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/CspHelper.html#method-i-csp_meta_tag)
+helper to create a meta tag "csp-nonce" with the per-session nonce value
+for allowing inline `<script>` tags.
+
+```html+erb
+<head>
+ <%= csp_meta_tag %>
+</head>
+```
+
+This is used by the Rails UJS helper to create dynamically
+loaded inline `<script>` elements.
+
Environmental Security
----------------------
diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
index 8df548b5de..806b7de6d6 100644
--- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
+++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
@@ -97,7 +97,7 @@ module Rails
elsif configurations[environment].blank? && configurations[connection].blank?
raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
else
- configurations[environment].presence || configurations[connection]
+ configurations[connection] || configurations[environment].presence
end
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index e1889979d7..8c5d872573 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -299,7 +299,7 @@ module Rails
def gem_for_database
# %w( mysql postgresql sqlite3 oracle frontbase ibm_db sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql )
case options[:database]
- when "mysql" then ["mysql2", ["~> 0.4.4"]]
+ when "mysql" then ["mysql2", [">= 0.4.4", "< 0.6.0"]]
when "postgresql" then ["pg", [">= 0.18", "< 2.0"]]
when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
when "frontbase" then ["ruby-frontbase", nil]