aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock2
-rw-r--r--actioncable/Rakefile36
-rw-r--r--actionpack/CHANGELOG.md4
-rw-r--r--actionpack/lib/action_controller/base.rb8
-rw-r--r--actionpack/lib/action_controller/metal.rb4
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_flash.rb4
-rw-r--r--actionpack/lib/action_controller/metal/force_ssl.rb14
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb2
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb6
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb2
-rw-r--r--actionpack/lib/action_controller/metal/live.rb8
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb4
-rw-r--r--actionpack/lib/action_controller/metal/parameter_encoding.rb2
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb8
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb4
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb2
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb10
-rw-r--r--actionpack/lib/action_controller/metal/rescue.rb2
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb16
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb2
-rw-r--r--actionpack/lib/action_controller/railtie.rb2
-rw-r--r--actionpack/lib/action_controller/renderer.rb6
-rw-r--r--actionpack/lib/action_controller/test_case.rb10
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb39
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb2
-rw-r--r--actionpack/test/controller/renderer_test.rb10
-rw-r--r--actionview/CHANGELOG.md6
-rw-r--r--activemodel/lib/active_model/type.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb79
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb33
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb146
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb32
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb43
-rw-r--r--activerecord/lib/active_record/type/serialized.rb2
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb6
-rw-r--r--activesupport/CHANGELOG.md18
-rw-r--r--railties/CHANGELOG.md4
43 files changed, 328 insertions, 293 deletions
diff --git a/Gemfile b/Gemfile
index a0da9d391f..924232d701 100644
--- a/Gemfile
+++ b/Gemfile
@@ -84,6 +84,7 @@ group :cable do
gem "blade", require: false, platforms: [:ruby]
gem "blade-sauce_labs_plugin", require: false, platforms: [:ruby]
+ gem "sprockets-export", require: false
end
# Add your own local bundler stuff.
diff --git a/Gemfile.lock b/Gemfile.lock
index 74f76f9e7c..68c69f75a0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -319,6 +319,7 @@ GEM
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
+ sprockets-export (0.9.1)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
@@ -414,6 +415,7 @@ DEPENDENCIES
sequel
sidekiq
sneakers
+ sprockets-export
sqlite3 (~> 1.3.6)
stackprof
sucker_punch
diff --git a/actioncable/Rakefile b/actioncable/Rakefile
index 87d443919c..bda8c7b6c8 100644
--- a/actioncable/Rakefile
+++ b/actioncable/Rakefile
@@ -1,12 +1,13 @@
require "rake/testtask"
require "pathname"
+require "open3"
require "action_cable"
dir = File.dirname(__FILE__)
task default: :test
-task package: "assets:compile"
+task package: %w( assets:compile assets:verify )
Rake::TestTask.new do |t|
t.libs << "test"
@@ -37,6 +38,39 @@ namespace :assets do
desc "Compile Action Cable assets"
task :compile do
require "blade"
+ require "sprockets"
+ require "sprockets/export"
Blade.build
end
+
+ desc "Verify compiled Action Cable assets"
+ task :verify do
+ file = "lib/assets/compiled/action_cable.js"
+ pathname = Pathname.new("#{dir}/#{file}")
+
+ print "[verify] #{file} exists "
+ if pathname.exist?
+ puts "[OK]"
+ else
+ $stderr.puts "[FAIL]"
+ fail
+ end
+
+ print "[verify] #{file} is a UMD module "
+ if pathname.read =~ /module\.exports.*define\.amd/m
+ puts "[OK]"
+ else
+ $stderr.puts "[FAIL]"
+ fail
+ end
+
+ print "[verify] #{dir} can be required as a module "
+ stdout, stderr, status = Open3.capture3("node", "--print", "window = {}; require('#{dir}');")
+ if status.success?
+ puts "[OK]"
+ else
+ $stderr.puts "[FAIL]\n#{stderr}"
+ fail
+ end
+ end
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 770bda1d44..d0662bdae2 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Fix `NameError` raised in `ActionController::Renderer#with_defaults`
+
+ *Hiroyuki Ishii*
+
* Added `#reverse_merge` and `#reverse_merge!` methods to `ActionController::Parameters`
*Edouard Chin*, *Mitsutaka Mimura*
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index ca8066cd82..0fe0853da3 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -8,7 +8,7 @@ module ActionController
# on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
#
# By default, only the ApplicationController in a \Rails application inherits from <tt>ActionController::Base</tt>. All other
- # controllers in turn inherit from ApplicationController. This gives you one class to configure things such as
+ # controllers inherit from ApplicationController. This gives you one class to configure things such as
# request forgery protection and filtering of sensitive request parameters.
#
# A sample controller could look like this:
@@ -30,7 +30,7 @@ module ActionController
#
# Unlike index, the create action will not render a template. After performing its main purpose (creating a
# new post), it initiates a redirect instead. This redirect works by returning an external
- # "302 Moved" HTTP response that takes the user to the index action.
+ # <tt>302 Moved</tt> HTTP response that takes the user to the index action.
#
# These two methods represent the two basic action archetypes used in Action Controllers: Get-and-show and do-and-redirect.
# Most actions are variations on these themes.
@@ -59,7 +59,7 @@ module ActionController
# <input type="text" name="post[name]" value="david">
# <input type="text" name="post[address]" value="hyacintvej">
#
- # A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
+ # A request coming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
# If the address input had been named <tt>post[address][street]</tt>, the <tt>params</tt> would have included
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
#
@@ -74,7 +74,7 @@ module ActionController
#
# session[:person] = Person.authenticate(user_name, password)
#
- # And retrieved again through the same hash:
+ # You can retrieve it again through the same hash:
#
# Hello #{session[:person]}
#
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 337718afc0..74c4153cd2 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -138,7 +138,7 @@ module ActionController
false
end
- # Delegates to the class' <tt>controller_name</tt>
+ # Delegates to the class' <tt>controller_name</tt>.
def controller_name
self.class.controller_name
end
@@ -244,7 +244,7 @@ module ActionController
end
end
- # Direct dispatch to the controller. Instantiates the controller, then
+ # Direct dispatch to the controller. Instantiates the controller, then
# executes the action named +name+.
def self.dispatch(name, req, res)
if middleware_stack.any?
diff --git a/actionpack/lib/action_controller/metal/etag_with_flash.rb b/actionpack/lib/action_controller/metal/etag_with_flash.rb
index 474d75f02e..7bd338bd7c 100644
--- a/actionpack/lib/action_controller/metal/etag_with_flash.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_flash.rb
@@ -1,9 +1,9 @@
module ActionController
# When you're using the flash, it's generally used as a conditional on the view.
# This means the content of the view depends on the flash. Which in turn means
- # that the etag for a response should be computed with the content of the flash
+ # that the ETag for a response should be computed with the content of the flash
# in mind. This does that by including the content of the flash as a component
- # in the etag that's generated for a response.
+ # in the ETag that's generated for a response.
module EtagWithFlash
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb
index 9d43e752ac..73e67573ca 100644
--- a/actionpack/lib/action_controller/metal/force_ssl.rb
+++ b/actionpack/lib/action_controller/metal/force_ssl.rb
@@ -2,17 +2,17 @@ require "active_support/core_ext/hash/except"
require "active_support/core_ext/hash/slice"
module ActionController
- # This module provides a method which will redirect the browser to use HTTPS
- # protocol. This will ensure that user's sensitive information will be
+ # This module provides a method which will redirect the browser to use the secured HTTPS
+ # protocol. This will ensure that users' sensitive information will be
# transferred safely over the internet. You _should_ always force the browser
# to use HTTPS when you're transferring sensitive information such as
# user authentication, account information, or credit card information.
#
# Note that if you are really concerned about your application security,
# you might consider using +config.force_ssl+ in your config file instead.
- # That will ensure all the data transferred via HTTPS protocol and prevent
- # the user from getting their session hijacked when accessing the site over
- # unsecured HTTP protocol.
+ # That will ensure all the data is transferred via HTTPS, and will
+ # prevent the user from getting their session hijacked when accessing the
+ # site over unsecured HTTP protocol.
module ForceSSL
extend ActiveSupport::Concern
include AbstractController::Callbacks
@@ -23,7 +23,7 @@ module ActionController
module ClassMethods
# Force the request to this particular controller or specified actions to be
- # under HTTPS protocol.
+ # through the HTTPS protocol.
#
# If you need to disable this for any reason (e.g. development) then you can use
# an +:if+ or +:unless+ condition.
@@ -71,7 +71,7 @@ module ActionController
# Redirect the existing request to use the HTTPS protocol.
#
# ==== Parameters
- # * <tt>host_or_options</tt> - Either a host name or any of the url &
+ # * <tt>host_or_options</tt> - Either a host name or any of the url and
# redirect options available to the <tt>force_ssl</tt> method.
def force_ssl_redirect(host_or_options = nil)
unless request.ssl?
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 0575360068..d8bc895265 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -445,7 +445,7 @@ module ActionController
end
end
- # Parses the token and options out of the token authorization header.
+ # Parses the token and options out of the token Authorization header.
# The value for the Authorization header is expected to have the prefix
# <tt>"Token"</tt> or <tt>"Bearer"</tt>. If the header looks like this:
# Authorization: Token token="abc", nonce="def"
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index dde924e682..eeb27f99f4 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -2,11 +2,11 @@ module ActionController
# Handles implicit rendering for a controller action that does not
# explicitly respond with +render+, +respond_to+, +redirect+, or +head+.
#
- # For API controllers, the implicit response is always 204 No Content.
+ # For API controllers, the implicit response is always <tt>204 No Content</tt>.
#
# For all other controllers, we use these heuristics to decide whether to
# render a template, raise an error for a missing template, or respond with
- # 204 No Content:
+ # <tt>204 No Content</tt>:
#
# First, if we DO find a template, it's rendered. Template lookup accounts
# for the action name, locales, format, variant, template handlers, and more
@@ -23,7 +23,7 @@ module ActionController
# <tt>ActionView::UnknownFormat</tt> with an explanation.
#
# Finally, if we DON'T find a template AND the request isn't a browser page
- # load, then we implicitly respond with 204 No Content.
+ # load, then we implicitly respond with <tt>204 No Content</tt>.
module ImplicitRender
# :stopdoc:
include BasicImplicitRender
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 924686218f..2485d27cec 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -3,7 +3,7 @@ require "abstract_controller/logger"
module ActionController
# Adds instrumentation to several ends in ActionController::Base. It also provides
- # some hooks related with process_action, this allows an ORM like Active Record
+ # some hooks related with process_action. This allows an ORM like Active Record
# and/or DataMapper to plug in ActionController and show related information.
#
# Check ActiveRecord::Railties::ControllerRuntime for an example.
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index fed99e6c82..a607ee2309 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -239,8 +239,8 @@ module ActionController
error = nil
# This processes the action in a child thread. It lets us return the
- # response code and headers back up the rack stack, and still process
- # the body in parallel with sending data to the client
+ # response code and headers back up the Rack stack, and still process
+ # the body in parallel with sending data to the client.
new_controller_thread {
ActiveSupport::Dependencies.interlock.running do
t2 = Thread.current
@@ -278,9 +278,9 @@ module ActionController
raise error if error
end
- # Spawn a new thread to serve up the controller in. This is to get
+ # Spawn a new thread to serve up the controller in. This is to get
# around the fact that Rack isn't based around IOs and we need to use
- # a thread to stream data from the response bodies. Nobody should call
+ # a thread to stream data from the response bodies. Nobody should call
# this method except in Rails internals. Seriously!
def new_controller_thread # :nodoc:
Thread.new {
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index f6aabcb102..7b4c7b923e 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -181,8 +181,8 @@ module ActionController #:nodoc:
#
# request.variant = [:tablet, :phone]
#
- # which will work similarly to formats and MIME types negotiation. If there will be no
- # +:tablet+ variant declared, +:phone+ variant will be picked:
+ # This will work similarly to formats and MIME types negotiation. If there
+ # is no +:tablet+ variant declared, +:phone+ variant will be picked:
#
# respond_to do |format|
# format.html.none
diff --git a/actionpack/lib/action_controller/metal/parameter_encoding.rb b/actionpack/lib/action_controller/metal/parameter_encoding.rb
index 962532ff09..ecc691619e 100644
--- a/actionpack/lib/action_controller/metal/parameter_encoding.rb
+++ b/actionpack/lib/action_controller/metal/parameter_encoding.rb
@@ -39,7 +39,7 @@ module ActionController
# end
#
# The show action in the above controller would have all parameter values
- # encoded as ASCII-8BIT. This is useful in the case where an application
+ # encoded as ASCII-8BIT. This is useful in the case where an application
# must handle data but encoding of the data is unknown, like file system data.
def skip_parameter_encoding(action)
@_parameter_encodings[action.to_s] = true
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 7fc898f034..3cca5e8906 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -213,7 +213,7 @@ module ActionController
end
# Sets the default wrapper key or model which will be used to determine
- # wrapper key and attribute names. Will be called automatically when the
+ # wrapper key and attribute names. Called automatically when the
# module is inherited.
def inherited(klass)
if klass._wrapper_options.format.any?
@@ -225,7 +225,7 @@ module ActionController
end
end
- # Performs parameters wrapping upon the request. Will be called automatically
+ # Performs parameters wrapping upon the request. Called automatically
# by the metal call stack.
def process_action(*args)
if _wrapper_enabled?
@@ -238,11 +238,11 @@ module ActionController
wrapped_keys = request.request_parameters.keys
wrapped_filtered_hash = _wrap_parameters request.filtered_parameters.slice(*wrapped_keys)
- # This will make the wrapped hash accessible from controller and view
+ # This will make the wrapped hash accessible from controller and view.
request.parameters.merge! wrapped_hash
request.request_parameters.merge! wrapped_hash
- # This will display the wrapped hash in the log file
+ # This will display the wrapped hash in the log file.
request.filtered_parameters.merge! wrapped_filtered_hash
end
super
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 1836a07d4e..fdfe82f96b 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -22,7 +22,7 @@ module ActionController
# redirect_to posts_url
# redirect_to proc { edit_post_url(@post) }
#
- # The redirection happens as a "302 Found" header unless otherwise specified using the <tt>:status</tt> option:
+ # The redirection happens as a <tt>302 Found</tt> header unless otherwise specified using the <tt>:status</tt> option:
#
# redirect_to post_url(@post), status: :found
# redirect_to action: 'atom', status: :moved_permanently
@@ -36,7 +36,7 @@ module ActionController
# If you are using XHR requests other than GET or POST and redirecting after the
# request then some browsers will follow the redirect using the original request
# method. This may lead to undesirable behavior such as a double DELETE. To work
- # around this you can return a <tt>303 See Other</tt> status code which will be
+ # around this you can return a <tt>303 See Other</tt> status code which will be
# followed using a GET request.
#
# redirect_to posts_url, status: :see_other
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 6b17719381..67f207afc2 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -36,7 +36,7 @@ module ActionController
super
end
- # Overwrite render_to_string because body can now be set to a rack body.
+ # Overwrite render_to_string because body can now be set to a Rack body.
def render_to_string(*)
result = super
if result.respond_to?(:each)
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index e8965a6561..d9a8b9c12d 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -262,9 +262,9 @@ module ActionController #:nodoc:
# Returns true or false if a request is verified. Checks:
#
- # * Is it a GET or HEAD request? Gets should be safe and idempotent
+ # * Is it a GET or HEAD request? GETs should be safe and idempotent
# * Does the form_authenticity_token match the given token value from the params?
- # * Does the X-CSRF-Token header match the form_authenticity_token
+ # * Does the X-CSRF-Token header match the form_authenticity_token?
def verified_request? # :doc:
!protect_against_forgery? || request.get? || request.head? ||
(valid_request_origin? && any_authenticity_token_valid?)
@@ -327,7 +327,7 @@ module ActionController #:nodoc:
if masked_token.length == AUTHENTICITY_TOKEN_LENGTH
# This is actually an unmasked token. This is expected if
# you have just upgraded to masked tokens, but should stop
- # happening shortly after installing this gem
+ # happening shortly after installing this gem.
compare_with_real_token masked_token, session
elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
@@ -336,13 +336,13 @@ module ActionController #:nodoc:
compare_with_real_token(csrf_token, session) ||
valid_per_form_csrf_token?(csrf_token, session)
else
- false # Token is malformed
+ false # Token is malformed.
end
end
def unmask_token(masked_token) # :doc:
# Split the token into the one-time pad and the encrypted
- # value and decrypt it
+ # value and decrypt it.
one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
encrypted_csrf_token = masked_token[AUTHENTICITY_TOKEN_LENGTH..-1]
xor_byte_strings(one_time_pad, encrypted_csrf_token)
diff --git a/actionpack/lib/action_controller/metal/rescue.rb b/actionpack/lib/action_controller/metal/rescue.rb
index 2d99e4045b..25757938f5 100644
--- a/actionpack/lib/action_controller/metal/rescue.rb
+++ b/actionpack/lib/action_controller/metal/rescue.rb
@@ -10,7 +10,7 @@ module ActionController #:nodoc:
# exceptions must be shown. This method is only called when
# consider_all_requests_local is false. By default, it returns
# false, but someone may set it to `request.local?` so local
- # requests in production still shows the detailed exception pages.
+ # requests in production still show the detailed exception pages.
def show_detailed_exceptions?
false
end
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 877a08b222..58cf60ad2a 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -3,7 +3,7 @@ require "rack/chunked"
module ActionController #:nodoc:
# Allows views to be streamed back to the client as they are rendered.
#
- # The default way Rails renders views is by first rendering the template
+ # By default, Rails renders views by first rendering the template
# and then the layout. The response is sent to the client after the whole
# template is rendered, all queries are made, and the layout is processed.
#
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 0217376ab3..1190e0ed69 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -262,7 +262,7 @@ module ActionController
alias_method :to_unsafe_hash, :to_unsafe_h
# Convert all hashes in values into parameters, then yield each pair in
- # the same way as <tt>Hash#each_pair</tt>
+ # the same way as <tt>Hash#each_pair</tt>.
def each_pair(&block)
@parameters.each_pair do |key, value|
yield key, convert_hashes_to_parameters(key, value)
@@ -410,7 +410,7 @@ module ActionController
#
# params.permit(preferences: {})
#
- # but be careful because this opens the door to arbitrary input. In this
+ # Be careful because this opens the door to arbitrary input. In this
# case, +permit+ ensures values in the returned structure are permitted
# scalars and filters out anything else.
#
@@ -646,15 +646,15 @@ module ActionController
end
# Returns a new <tt>ActionController::Parameters</tt> with all keys from
- # +other_hash+ merges into current hash.
+ # +other_hash+ merged into current hash.
def merge(other_hash)
new_instance_with_inherited_permitted_status(
@parameters.merge(other_hash.to_h)
)
end
- # Returns current <tt>ActionController::Parameters</tt> instance which
- # +other_hash+ merges into current hash.
+ # Returns current <tt>ActionController::Parameters</tt> instance with
+ # +other_hash+ merged into current hash.
def merge!(other_hash)
@parameters.merge!(other_hash.to_h)
self
@@ -715,7 +715,7 @@ module ActionController
undef_method :to_param
- # Returns duplicate of object including all parameters
+ # Returns duplicate of object including all parameters.
def deep_dup
self.class.new(@parameters.deep_dup).tap do |duplicate|
duplicate.permitted = @permitted
@@ -935,7 +935,7 @@ module ActionController
# whitelisted.
#
# In addition, parameters can be marked as required and flow through a
- # predefined raise/rescue flow to end up as a 400 Bad Request with no
+ # predefined raise/rescue flow to end up as a <tt>400 Bad Request</tt> with no
# effort.
#
# class PeopleController < ActionController::Base
@@ -959,7 +959,7 @@ module ActionController
#
# private
# # Using a private method to encapsulate the permissible parameters is
- # # just a good pattern since you'll be able to reuse the same permit
+ # # a good pattern since you'll be able to reuse the same permit
# # list between create and update. Also, you can specialize this method
# # with per-user checking of permissible attributes.
# def person_params
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 9f3cc099d6..21ed5b4ec8 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -3,7 +3,7 @@ module ActionController
# the <tt>_routes</tt> method. Otherwise, an exception will be raised.
#
# In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
- # url options like the +host+. In order to do so, this module requires the host class
+ # URL options like the +host+. In order to do so, this module requires the host class
# to implement +env+ which needs to be Rack-compatible and +request+
# which is either an instance of +ActionDispatch::Request+ or an object
# that responds to the +host+, +optional_port+, +protocol+ and
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index a7cdfe6a98..fadfc8de60 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -42,7 +42,7 @@ module ActionController
options.javascripts_dir ||= paths["public/javascripts"].first
options.stylesheets_dir ||= paths["public/stylesheets"].first
- # Ensure readers methods get compiled
+ # Ensure readers methods get compiled.
options.asset_host ||= app.config.asset_host
options.relative_url_root ||= app.config.relative_url_root
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index e1441bd343..cbb719d8b2 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -5,7 +5,7 @@ module ActionController
# without requirement of being in controller actions.
#
# You get a concrete renderer class by invoking ActionController::Base#renderer.
- # For example,
+ # For example:
#
# ApplicationController.renderer
#
@@ -18,7 +18,7 @@ module ActionController
# ApplicationController.render template: '...'
#
# #render allows you to use the same options that you can use when rendering in a controller.
- # For example,
+ # For example:
#
# FooController.render :action, locals: { ... }, assigns: { ... }
#
@@ -56,7 +56,7 @@ module ActionController
# Create a new renderer for the same controller but with new defaults.
def with_defaults(defaults)
- self.class.new controller, env, self.defaults.merge(defaults)
+ self.class.new controller, @env, self.defaults.merge(defaults)
end
# Accepts a custom Rack environment to render templates in.
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 7229c67f30..72e29c2c9d 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -13,10 +13,10 @@ module ActionController
end
module Live
- # Disable controller / rendering threads in tests. User tests can access
+ # Disable controller / rendering threads in tests. User tests can access
# the database on the main thread, so they could open a txn, then the
# controller thread will open a new connection and try to access data
- # that's only visible to the main thread's txn. This is the problem in #23483
+ # that's only visible to the main thread's txn. This is the problem in #23483.
remove_method :new_controller_thread
def new_controller_thread # :nodoc:
yield
@@ -35,7 +35,7 @@ module ActionController
attr_reader :controller_class
- # Create a new test request with default `env` values
+ # Create a new test request with default `env` values.
def self.create(controller_class)
env = {}
env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
@@ -131,7 +131,7 @@ module ActionController
include Rack::Test::Utils
def should_multipart?(params)
- # FIXME: lifted from Rack-Test. We should push this separation upstream
+ # FIXME: lifted from Rack-Test. We should push this separation upstream.
multipart = false
query = lambda { |value|
case value
@@ -300,7 +300,7 @@ module ActionController
# assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
# assert flash.empty? # makes sure that there's nothing in the flash
#
- # On top of the collections, you have the complete url that a given action redirected to available in <tt>redirect_to_url</tt>.
+ # On top of the collections, you have the complete URL that a given action redirected to available in <tt>redirect_to_url</tt>.
#
# For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
# action call which can then be asserted against.
diff --git a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
index 6de8fb74dc..3078e035a3 100644
--- a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
+++ b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
@@ -8,9 +8,20 @@ module ActionDispatch
# +take_screenshot+ can be used at any point in your system tests to take
# a screenshot of the current state. This can be useful for debugging or
# automating visual testing.
+ #
+ # The screenshot will be displayed in your console, if supported.
+ #
+ # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT+ environment variable to
+ # control the output. Possible values are:
+ # * [+inline+ (default)] display the screenshot in the terminal using the
+ # iTerm image protocol (http://iterm2.com/documentation-images.html).
+ # * [+simple+] only display the screenshot path.
+ # This is the default value if the +CI+ environment variables
+ # is defined.
+ # * [+artifact+] display the screenshot in the terminal, using the terminal
+ # artifact format (http://buildkite.github.io/terminal/inline-images/).
def take_screenshot
save_image
- puts "[Screenshot]: #{image_path}"
puts display_image
end
@@ -38,14 +49,32 @@ module ActionDispatch
page.save_screenshot(Rails.root.join(image_path))
end
+ def output_type
+ # Environment variables have priority
+ output_type = ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] || ENV["CAPYBARA_INLINE_SCREENSHOT"]
+
+ # If running in a CI environment, default to simple
+ output_type ||= "simple" if ENV["CI"]
+
+ # Default
+ output_type ||= "inline"
+
+ output_type
+ end
+
def display_image
- if ENV["CAPYBARA_INLINE_SCREENSHOT"] == "artifact"
- "\e]1338;url=artifact://#{image_path}\a"
- else
+ message = "[Screenshot]: #{image_path}\n"
+
+ case output_type
+ when "artifact"
+ message << "\e]1338;url=artifact://#{image_path}\a\n"
+ when "inline"
name = inline_base64(File.basename(image_path))
image = inline_base64(File.read(image_path))
- "\e]1337;File=name=#{name};height=400px;inline=1:#{image}\a"
+ message << "\e]1337;File=name=#{name};height=400px;inline=1:#{image}\a\n"
end
+
+ message
end
def inline_base64(path)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 5fa0b727ab..a3430e210e 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -572,7 +572,7 @@ module ActionDispatch
# end
#
# assert_response :success
- # assert_equal({ id: Arcticle.last.id, title: "Ahoy!" }, response.parsed_body)
+ # assert_equal({ id: Article.last.id, title: "Ahoy!" }, response.parsed_body)
# end
# end
#
diff --git a/actionpack/test/controller/renderer_test.rb b/actionpack/test/controller/renderer_test.rb
index 81b32a67b3..052c974d68 100644
--- a/actionpack/test/controller/renderer_test.rb
+++ b/actionpack/test/controller/renderer_test.rb
@@ -19,6 +19,16 @@ class RendererTest < ActiveSupport::TestCase
assert_equal controller, renderer.controller
end
+ test "creating with new defaults" do
+ renderer = ApplicationController.renderer
+
+ new_defaults = { https: true }
+ new_renderer = renderer.with_defaults(new_defaults).new
+ content = new_renderer.render(inline: "<%= request.ssl? %>")
+
+ assert_equal "true", content
+ end
+
test "rendering with a class renderer" do
renderer = ApplicationController.renderer
content = renderer.render template: "ruby_template"
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 58659a4588..6e71809385 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,7 +1,9 @@
* Remove the option `encode_special_chars` misnomer from `strip_tags`
- As of rails-html-sanitizer v1.0.3 sanitizer will ignore the
- `encode_special_chars` option. Fixes #28060.
+ As of rails-html-sanitizer v1.0.3, the sanitizer will ignore the
+ `encode_special_chars` option.
+
+ Fixes #28060.
*Andrew Hood*
diff --git a/activemodel/lib/active_model/type.rb b/activemodel/lib/active_model/type.rb
index b8e6d2376b..095801d8f0 100644
--- a/activemodel/lib/active_model/type.rb
+++ b/activemodel/lib/active_model/type.rb
@@ -21,16 +21,8 @@ module ActiveModel
class << self
attr_accessor :registry # :nodoc:
- delegate :add_modifier, to: :registry
- # Add a new type to the registry, allowing it to be referenced as a
- # symbol by ActiveRecord::Attributes::ClassMethods#attribute. If your
- # type is only meant to be used with a specific database adapter, you can
- # do so by passing +adapter: :postgresql+. If your type has the same
- # name as a native type for the current adapter, an exception will be
- # raised unless you specify an +:override+ option. +override: true+ will
- # cause your type to be used instead of the native type. +override:
- # false+ will cause the native type to be used over yours if one exists.
+ # Add a new type to the registry, allowing it to be get through ActiveModel::Type#lookup
def register(type_name, klass = nil, **options, &block)
registry.register(type_name, klass, **options, &block)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index a497a354f7..1e826ff5ad 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -31,6 +31,8 @@ module ActiveRecord
# Returns the relation names useable to back Active Record models.
# For most adapters this means all #tables and #views.
def data_sources
+ select_values(data_source_sql, "SCHEMA")
+ rescue NotImplementedError
tables | views
end
@@ -39,12 +41,14 @@ module ActiveRecord
# data_source_exists?(:ebooks)
#
def data_source_exists?(name)
+ select_values(data_source_sql(name), "SCHEMA").any? if name.present?
+ rescue NotImplementedError
data_sources.include?(name.to_s)
end
# Returns an array of table names defined in the database.
def tables
- raise NotImplementedError, "#tables is not implemented"
+ select_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
end
# Checks to see if the table +table_name+ exists on the database.
@@ -52,12 +56,14 @@ module ActiveRecord
# table_exists?(:developers)
#
def table_exists?(table_name)
+ select_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
+ rescue NotImplementedError
tables.include?(table_name.to_s)
end
# Returns an array of view names defined in the database.
def views
- raise NotImplementedError, "#views is not implemented"
+ select_values(data_source_sql(type: "VIEW"), "SCHEMA")
end
# Checks to see if the view +view_name+ exists on the database.
@@ -65,6 +71,8 @@ module ActiveRecord
# view_exists?(:ebooks)
#
def view_exists?(view_name)
+ select_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
+ rescue NotImplementedError
views.include?(view_name.to_s)
end
@@ -1304,6 +1312,14 @@ module ActiveRecord
def can_remove_index_by_name?(options)
options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
end
+
+ def data_source_sql(name = nil, type: nil)
+ raise NotImplementedError
+ end
+
+ def quoted_scope(name = nil, type: nil)
+ raise NotImplementedError
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index e3b6327dd8..55ec112c17 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -6,6 +6,7 @@ require "active_record/connection_adapters/mysql/quoting"
require "active_record/connection_adapters/mysql/schema_creation"
require "active_record/connection_adapters/mysql/schema_definitions"
require "active_record/connection_adapters/mysql/schema_dumper"
+require "active_record/connection_adapters/mysql/schema_statements"
require "active_record/connection_adapters/mysql/type_metadata"
require "active_support/core_ext/string/strip"
@@ -15,6 +16,7 @@ module ActiveRecord
class AbstractMysqlAdapter < AbstractAdapter
include MySQL::Quoting
include MySQL::ColumnDumper
+ include MySQL::SchemaStatements
def update_table_definition(table_name, base) # :nodoc:
MySQL::Table.new(table_name, base)
@@ -310,57 +312,6 @@ module ActiveRecord
show_variable "collation_database"
end
- def tables # :nodoc:
- sql = "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE'"
- sql << " AND table_schema = #{quote(@config[:database])}"
-
- select_values(sql, "SCHEMA")
- end
-
- def views # :nodoc:
- select_values("SHOW FULL TABLES WHERE table_type = 'VIEW'", "SCHEMA")
- end
-
- def data_sources # :nodoc:
- sql = "SELECT table_name FROM information_schema.tables "
- sql << "WHERE table_schema = #{quote(@config[:database])}"
-
- select_values(sql, "SCHEMA")
- end
-
- def table_exists?(table_name) # :nodoc:
- return false unless table_name.present?
-
- schema, name = extract_schema_qualified_name(table_name)
-
- sql = "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE'"
- sql << " AND table_schema = #{quote(schema)} AND table_name = #{quote(name)}"
-
- select_values(sql, "SCHEMA").any?
- end
-
- def data_source_exists?(table_name) # :nodoc:
- return false unless table_name.present?
-
- schema, name = extract_schema_qualified_name(table_name)
-
- sql = "SELECT table_name FROM information_schema.tables "
- sql << "WHERE table_schema = #{quote(schema)} AND table_name = #{quote(name)}"
-
- select_values(sql, "SCHEMA").any?
- end
-
- def view_exists?(view_name) # :nodoc:
- return false unless view_name.present?
-
- schema, name = extract_schema_qualified_name(view_name)
-
- sql = "SELECT table_name FROM information_schema.tables WHERE table_type = 'VIEW'"
- sql << " AND table_schema = #{quote(schema)} AND table_name = #{quote(name)}"
-
- select_values(sql, "SCHEMA").any?
- end
-
def truncate(table_name, name = nil)
execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
end
@@ -406,13 +357,13 @@ module ActiveRecord
end
def table_comment(table_name) # :nodoc:
- schema, name = extract_schema_qualified_name(table_name)
+ scope = quoted_scope(table_name)
select_value(<<-SQL.strip_heredoc, "SCHEMA")
SELECT table_comment
FROM information_schema.tables
- WHERE table_schema = #{quote(schema)}
- AND table_name = #{quote(name)}
+ WHERE table_schema = #{scope[:schema]}
+ AND table_name = #{scope[:name]}
SQL
end
@@ -512,7 +463,7 @@ module ActiveRecord
def foreign_keys(table_name)
raise ArgumentError unless table_name.present?
- schema, name = extract_schema_qualified_name(table_name)
+ scope = quoted_scope(table_name)
fk_info = select_all(<<-SQL.strip_heredoc, "SCHEMA")
SELECT fk.referenced_table_name AS 'to_table',
@@ -525,9 +476,9 @@ module ActiveRecord
JOIN information_schema.referential_constraints rc
USING (constraint_schema, constraint_name)
WHERE fk.referenced_column_name IS NOT NULL
- AND fk.table_schema = #{quote(schema)}
- AND fk.table_name = #{quote(name)}
- AND rc.table_name = #{quote(name)}
+ AND fk.table_schema = #{scope[:schema]}
+ AND fk.table_name = #{scope[:name]}
+ AND rc.table_name = #{scope[:name]}
SQL
fk_info.map do |row|
@@ -599,14 +550,14 @@ module ActiveRecord
def primary_keys(table_name) # :nodoc:
raise ArgumentError unless table_name.present?
- schema, name = extract_schema_qualified_name(table_name)
+ scope = quoted_scope(table_name)
select_values(<<-SQL.strip_heredoc, "SCHEMA")
SELECT column_name
FROM information_schema.key_column_usage
WHERE constraint_name = 'PRIMARY'
- AND table_schema = #{quote(schema)}
- AND table_name = #{quote(name)}
+ AND table_schema = #{scope[:schema]}
+ AND table_name = #{scope[:name]}
ORDER BY ordinal_position
SQL
end
@@ -940,12 +891,6 @@ module ActiveRecord
)
end
- def extract_schema_qualified_name(string) # :nodoc:
- schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
- schema, name = @config[:database], schema unless name
- [schema, name]
- end
-
def integer_to_sql(limit) # :nodoc:
case limit
when 1; "tinyint"
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb
new file mode 100644
index 0000000000..10c8bd179a
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb
@@ -0,0 +1,33 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module MySQL
+ module SchemaStatements # :nodoc:
+ private
+ def data_source_sql(name = nil, type: nil)
+ scope = quoted_scope(name, type: type)
+
+ sql = "SELECT table_name FROM information_schema.tables"
+ sql << " WHERE table_schema = #{scope[:schema]}"
+ sql << " AND table_name = #{scope[:name]}" if scope[:name]
+ sql << " AND table_type = #{scope[:type]}" if scope[:type]
+ sql
+ end
+
+ def quoted_scope(name = nil, type: nil)
+ schema, name = extract_schema_qualified_name(name)
+ scope = {}
+ scope[:schema] = schema ? quote(schema) : "database()"
+ scope[:name] = quote(name) if name
+ scope[:type] = quote(type) if type
+ scope
+ end
+
+ def extract_schema_qualified_name(string)
+ schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
+ schema, name = nil, schema unless name
+ [schema, name]
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb b/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb
index 24dcf852e1..9ad6a6c0d0 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb
@@ -2,6 +2,8 @@ module ActiveRecord
module ConnectionAdapters
module MySQL
class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc:
+ undef to_yaml if method_defined?(:to_yaml)
+
attr_reader :extra
def initialize(type_metadata, extra: "")
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 afef0da5c7..a332375b78 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -54,81 +54,13 @@ module ActiveRecord
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
end
- # Returns the list of all tables in the schema search path.
- def tables
- select_values("SELECT tablename FROM pg_tables WHERE schemaname = ANY(current_schemas(false))", "SCHEMA")
- end
-
- def data_sources # :nodoc
- select_values(<<-SQL, "SCHEMA")
- SELECT c.relname
- FROM pg_class c
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
- WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view
- AND n.nspname = ANY (current_schemas(false))
- SQL
- end
-
- def views # :nodoc:
- select_values(<<-SQL, "SCHEMA")
- SELECT c.relname
- FROM pg_class c
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
- WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
- AND n.nspname = ANY (current_schemas(false))
- SQL
- end
-
- # Returns true if table exists.
- # If the schema is not specified as part of +name+ then it will only find tables within
- # the current schema search path (regardless of permissions to access tables in other schemas)
- def table_exists?(name)
- name = Utils.extract_schema_qualified_name(name.to_s)
- return false unless name.identifier
-
- select_values(<<-SQL, "SCHEMA").any?
- SELECT tablename
- FROM pg_tables
- WHERE tablename = #{quote(name.identifier)}
- AND schemaname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
- SQL
- end
-
- def data_source_exists?(name) # :nodoc:
- name = Utils.extract_schema_qualified_name(name.to_s)
- return false unless name.identifier
-
- select_values(<<-SQL, "SCHEMA").any?
- SELECT c.relname
- FROM pg_class c
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
- WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view
- AND c.relname = #{quote(name.identifier)}
- AND n.nspname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
- SQL
- end
-
- def view_exists?(view_name) # :nodoc:
- name = Utils.extract_schema_qualified_name(view_name.to_s)
- return false unless name.identifier
-
- select_values(<<-SQL, "SCHEMA").any?
- SELECT c.relname
- FROM pg_class c
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
- WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
- AND c.relname = #{quote(name.identifier)}
- AND n.nspname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
- SQL
- end
-
def drop_table(table_name, options = {}) # :nodoc:
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
end
# Returns true if schema exists.
def schema_exists?(name)
- select_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = '#{name}'", "SCHEMA").to_i > 0
+ select_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = #{quote(name)}", "SCHEMA").to_i > 0
end
# Verifies existence of an index with a given name.
@@ -138,8 +70,8 @@ module ActiveRecord
Passing default to #index_name_exists? is deprecated without replacement.
MSG
end
- table = Utils.extract_schema_qualified_name(table_name.to_s)
- index = Utils.extract_schema_qualified_name(index_name.to_s)
+ table = quoted_scope(table_name)
+ index = quoted_scope(index_name)
select_value(<<-SQL, "SCHEMA").to_i > 0
SELECT COUNT(*)
@@ -148,9 +80,9 @@ module ActiveRecord
INNER JOIN pg_class i ON d.indexrelid = i.oid
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
WHERE i.relkind = 'i'
- AND i.relname = '#{index.identifier}'
- AND t.relname = '#{table.identifier}'
- AND n.nspname = #{index.schema ? "'#{index.schema}'" : 'ANY (current_schemas(false))'}
+ AND i.relname = #{index[:name]}
+ AND t.relname = #{table[:name]}
+ AND n.nspname = #{index[:schema]}
SQL
end
@@ -162,7 +94,7 @@ module ActiveRecord
MSG
end
- table = Utils.extract_schema_qualified_name(table_name.to_s)
+ scope = quoted_scope(table_name)
result = query(<<-SQL, "SCHEMA")
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
@@ -176,8 +108,8 @@ module ActiveRecord
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
WHERE i.relkind = 'i'
AND d.indisprimary = 'f'
- AND t.relname = '#{table.identifier}'
- AND n.nspname = #{table.schema ? "'#{table.schema}'" : 'ANY (current_schemas(false))'}
+ AND t.relname = #{scope[:name]}
+ AND n.nspname = #{scope[:schema]}
ORDER BY i.relname
SQL
@@ -239,22 +171,22 @@ module ActiveRecord
# Returns a comment stored in database for given table
def table_comment(table_name) # :nodoc:
- name = Utils.extract_schema_qualified_name(table_name.to_s)
- if name.identifier
+ scope = quoted_scope(table_name, type: "BASE TABLE")
+ if scope[:name]
select_value(<<-SQL.strip_heredoc, "SCHEMA")
SELECT pg_catalog.obj_description(c.oid, 'pg_class')
FROM pg_catalog.pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
- WHERE c.relname = #{quote(name.identifier)}
- AND c.relkind IN ('r') -- (r)elation/table
- AND n.nspname = #{name.schema ? quote(name.schema) : 'ANY (current_schemas(false))'}
+ WHERE c.relname = #{scope[:name]}
+ AND c.relkind IN (#{scope[:type]})
+ AND n.nspname = #{scope[:schema]}
SQL
end
end
# Returns the current database name.
def current_database
- select_value("select current_database()", "SCHEMA")
+ select_value("SELECT current_database()", "SCHEMA")
end
# Returns the current schema name.
@@ -430,17 +362,15 @@ module ActiveRecord
end
def primary_keys(table_name) # :nodoc:
- name = Utils.extract_schema_qualified_name(table_name.to_s)
+ scope = quoted_scope(table_name)
select_values(<<-SQL.strip_heredoc, "SCHEMA")
SELECT column_name
FROM information_schema.key_column_usage kcu
JOIN information_schema.table_constraints tc
- ON kcu.table_name = tc.table_name
- AND kcu.table_schema = tc.table_schema
- AND kcu.constraint_name = tc.constraint_name
+ USING (table_schema, table_name, constraint_name)
WHERE constraint_type = 'PRIMARY KEY'
- AND kcu.table_name = #{quote(name.identifier)}
- AND kcu.table_schema = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
+ AND kcu.table_name = #{scope[:name]}
+ AND kcu.table_schema = #{scope[:schema]}
ORDER BY kcu.ordinal_position
SQL
end
@@ -579,6 +509,7 @@ module ActiveRecord
end
def foreign_keys(table_name)
+ scope = quoted_scope(table_name)
fk_info = select_all(<<-SQL.strip_heredoc, "SCHEMA")
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
@@ -588,8 +519,8 @@ module ActiveRecord
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
JOIN pg_namespace t3 ON c.connamespace = t3.oid
WHERE c.contype = 'f'
- AND t1.relname = #{quote(table_name)}
- AND t3.nspname = ANY (current_schemas(false))
+ AND t1.relname = #{scope[:name]}
+ AND t3.nspname = #{scope[:schema]}
ORDER BY c.conname
SQL
@@ -673,6 +604,39 @@ module ActiveRecord
)
PostgreSQLTypeMetadata.new(simple_type, oid: oid, fmod: fmod)
end
+
+ private
+ def data_source_sql(name = nil, type: nil)
+ scope = quoted_scope(name, type: type)
+ scope[:type] ||= "'r','v','m'" # (r)elation/table, (v)iew, (m)aterialized view
+
+ sql = "SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
+ sql << " WHERE n.nspname = #{scope[:schema]}"
+ sql << " AND c.relname = #{scope[:name]}" if scope[:name]
+ sql << " AND c.relkind IN (#{scope[:type]})"
+ sql
+ end
+
+ def quoted_scope(name = nil, type: nil)
+ schema, name = extract_schema_qualified_name(name)
+ type = \
+ case type
+ when "BASE TABLE"
+ "'r'"
+ when "VIEW"
+ "'v','m'"
+ end
+ scope = {}
+ scope[:schema] = schema ? quote(schema) : "ANY (current_schemas(false))"
+ scope[:name] = quote(name) if name
+ scope[:type] = type if type
+ scope
+ end
+
+ def extract_schema_qualified_name(string)
+ name = Utils.extract_schema_qualified_name(string.to_s)
+ [name.schema, name.identifier]
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb
index 311988625f..f57179ae59 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb
@@ -1,6 +1,8 @@
module ActiveRecord
module ConnectionAdapters
class PostgreSQLTypeMetadata < DelegateClass(SqlTypeMetadata)
+ undef to_yaml if method_defined?(:to_yaml)
+
attr_reader :oid, :fmod, :array
def initialize(type_metadata, oid: nil, fmod: nil)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index bc04565434..9f419f909f 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -3,6 +3,7 @@ gem "pg", "~> 0.18"
require "pg"
require "active_record/connection_adapters/abstract_adapter"
+require "active_record/connection_adapters/statement_pool"
require "active_record/connection_adapters/postgresql/column"
require "active_record/connection_adapters/postgresql/database_statements"
require "active_record/connection_adapters/postgresql/explain_pretty_printer"
@@ -15,7 +16,6 @@ require "active_record/connection_adapters/postgresql/schema_dumper"
require "active_record/connection_adapters/postgresql/schema_statements"
require "active_record/connection_adapters/postgresql/type_metadata"
require "active_record/connection_adapters/postgresql/utils"
-require "active_record/connection_adapters/statement_pool"
module ActiveRecord
module ConnectionHandling # :nodoc:
@@ -568,13 +568,13 @@ module ActiveRecord
if supports_ranges?
query = <<-SQL
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
+ SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
FROM pg_type as t
LEFT JOIN pg_range as r ON oid = rngtypid
SQL
else
query = <<-SQL
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
+ SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
FROM pg_type as t
SQL
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
new file mode 100644
index 0000000000..4ba245a0d8
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
@@ -0,0 +1,32 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module SQLite3
+ module SchemaStatements # :nodoc:
+ private
+ def data_source_sql(name = nil, type: nil)
+ scope = quoted_scope(name, type: type)
+ scope[:type] ||= "'table','view'"
+
+ sql = "SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence'"
+ sql << " AND name = #{scope[:name]}" if scope[:name]
+ sql << " AND type IN (#{scope[:type]})"
+ sql
+ end
+
+ def quoted_scope(name = nil, type: nil)
+ type = \
+ case type
+ when "BASE TABLE"
+ "'table'"
+ when "VIEW"
+ "'view'"
+ end
+ scope = {}
+ scope[:name] = quote(name) if name
+ scope[:type] = type if type
+ scope
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 8b627a6d4d..d24bfc0c93 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -5,6 +5,7 @@ require "active_record/connection_adapters/sqlite3/quoting"
require "active_record/connection_adapters/sqlite3/schema_creation"
require "active_record/connection_adapters/sqlite3/schema_definitions"
require "active_record/connection_adapters/sqlite3/schema_dumper"
+require "active_record/connection_adapters/sqlite3/schema_statements"
gem "sqlite3", "~> 1.3.6"
require "sqlite3"
@@ -55,6 +56,7 @@ module ActiveRecord
include SQLite3::Quoting
include SQLite3::ColumnDumper
+ include SQLite3::SchemaStatements
NATIVE_DATABASE_TYPES = {
primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
@@ -265,45 +267,6 @@ module ActiveRecord
# SCHEMA STATEMENTS ========================================
- def tables # :nodoc:
- select_values("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'", "SCHEMA")
- end
-
- def data_sources # :nodoc:
- select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", "SCHEMA")
- end
-
- def views # :nodoc:
- select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", "SCHEMA")
- end
-
- def table_exists?(table_name) # :nodoc:
- return false unless table_name.present?
-
- sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'"
- sql << " AND name = #{quote(table_name)}"
-
- select_values(sql, "SCHEMA").any?
- end
-
- def data_source_exists?(table_name) # :nodoc:
- return false unless table_name.present?
-
- sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
- sql << " AND name = #{quote(table_name)}"
-
- select_values(sql, "SCHEMA").any?
- end
-
- def view_exists?(view_name) # :nodoc:
- return false unless view_name.present?
-
- sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
- sql << " AND name = #{quote(view_name)}"
-
- select_values(sql, "SCHEMA").any?
- end
-
def new_column_from_field(table_name, field) # :nondoc:
case field["dflt_value"]
when /^null$/i
@@ -535,7 +498,7 @@ module ActiveRecord
end
def sqlite_version
- @sqlite_version ||= SQLite3Adapter::Version.new(select_value("select sqlite_version(*)"))
+ @sqlite_version ||= SQLite3Adapter::Version.new(select_value("SELECT sqlite_version(*)"))
end
def translate_exception(exception, message)
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb
index 6af05c1860..edbd20a6c1 100644
--- a/activerecord/lib/active_record/type/serialized.rb
+++ b/activerecord/lib/active_record/type/serialized.rb
@@ -1,6 +1,8 @@
module ActiveRecord
module Type
class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc:
+ undef to_yaml if method_defined?(:to_yaml)
+
include ActiveModel::Type::Helpers::Mutable
attr_reader :subtype, :coder
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index fdd7b0157a..2179d1294c 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -260,8 +260,7 @@ module ActiveRecord
def test_tables_logs_name
sql = <<-SQL
- SELECT name FROM sqlite_master
- WHERE type = 'table' AND name <> 'sqlite_sequence'
+ SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence' AND type IN ('table')
SQL
assert_logged [[sql.squish, "SCHEMA", []]] do
@conn.tables
@@ -279,8 +278,7 @@ module ActiveRecord
def test_table_exists_logs_name
with_example_table do
sql = <<-SQL
- SELECT name FROM sqlite_master
- WHERE type = 'table' AND name <> 'sqlite_sequence' AND name = 'ex'
+ SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence' AND name = 'ex' AND type IN ('table')
SQL
assert_logged [[sql.squish, "SCHEMA", []]] do
assert @conn.table_exists?("ex")
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 2cee8375b7..de1418bb86 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,7 +1,7 @@
* Update `titleize` regex to allow apostrophes
In 4b685aa the regex in `titleize` was updated to not match apostrophes to
- better reflect the nature of the transformation. Unfortunately this had the
+ better reflect the nature of the transformation. Unfortunately, this had the
side effect of breaking capitalization on the first word of a sub-string, e.g:
>> "This was 'fake news'".titleize
@@ -22,7 +22,7 @@
* Add `Time.rfc3339` parsing method
- The `Time.xmlschema` and consequently its alias `iso8601` accepts timestamps
+ `Time.xmlschema` and consequently its alias `iso8601` accepts timestamps
without a offset in contravention of the RFC 3339 standard. This method
enforces that constraint and raises an `ArgumentError` if it doesn't.
@@ -30,7 +30,7 @@
* Add `ActiveSupport::TimeZone.rfc3339` parsing method
- Previously there was no way to get a RFC 3339 timestamp into a specific
+ Previously, there was no way to get a RFC 3339 timestamp into a specific
timezone without either using `parse` or chaining methods. The new method
allows parsing directly into the timezone, e.g:
@@ -39,7 +39,7 @@
>> Time.zone.rfc3339("1999-12-31T14:00:00Z")
=> Fri, 31 Dec 1999 14:00:00 HST -10:00
- This new method has stricter semantics than the current `parse` method
+ This new method has stricter semantics than the current `parse` method,
and will raise an `ArgumentError` instead of returning nil, e.g:
>> Time.zone = "Hawaii"
@@ -63,7 +63,7 @@
* Add `ActiveSupport::TimeZone.iso8601` parsing method
- Previously there was no way to get a ISO 8601 timestamp into a specific
+ Previously, there was no way to get a ISO 8601 timestamp into a specific
timezone without either using `parse` or chaining methods. The new method
allows parsing directly into the timezone, e.g:
@@ -72,7 +72,7 @@
>> Time.zone.iso8601("1999-12-31T14:00:00Z")
=> Fri, 31 Dec 1999 14:00:00 HST -10:00
- If the timestamp is a ISO 8601 date (YYYY-MM-DD) then the time is set
+ If the timestamp is a ISO 8601 date (YYYY-MM-DD), then the time is set
to midnight, e.g:
>> Time.zone = "Hawaii"
@@ -80,7 +80,7 @@
>> Time.zone.iso8601("1999-12-31")
=> Fri, 31 Dec 1999 00:00:00 HST -10:00
- This new method has stricter semantics than the current `parse` method
+ This new method has stricter semantics than the current `parse` method,
and will raise an `ArgumentError` instead of returning nil, e.g:
>> Time.zone = "Hawaii"
@@ -175,7 +175,9 @@
* Soft-deprecated the top-level `HashWithIndifferentAccess` constant.
`ActiveSupport::HashWithIndifferentAccess` should be used instead.
- *Robin Dupret* (#28157)
+ Fixes #28157.
+
+ *Robin Dupret*
* In Core Extensions, make `MarshalWithAutoloading#load` pass through the second, optional
argument for `Marshal#load( source [, proc] )`. This way we don't have to do
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 9b6ceff9ff..bc5f696675 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,7 +1,9 @@
* Avoid running system tests by default with the `bin/rails test`
and `bin/rake test` commands since they may be expensive.
- *Robin Dupret* (#28286)
+ Fixes #28286.
+
+ *Robin Dupret*
* Improve encryption for encrypted secrets.