aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md8
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb6
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb7
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb2
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb6
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb2
-rw-r--r--actionpack/test/controller/mime/respond_to_test.rb23
-rw-r--r--actionview/CHANGELOG.md6
-rw-r--r--actionview/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionview/lib/action_view/helpers/translation_helper.rb2
-rw-r--r--actionview/lib/action_view/lookup_context.rb2
-rw-r--r--actionview/test/template/translation_helper_test.rb5
-rw-r--r--activemodel/CHANGELOG.md8
-rw-r--r--activemodel/lib/active_model/validations.rb2
-rw-r--r--activemodel/lib/active_model/validations/callbacks.rb2
-rw-r--r--activemodel/lib/active_model/validations/length.rb2
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb2
-rw-r--r--activerecord/lib/active_record/callbacks.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb15
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/core.rb8
-rw-r--r--activerecord/lib/active_record/log_subscriber.rb3
-rw-r--r--activerecord/lib/active_record/railties/controller_runtime.rb2
-rw-r--r--activerecord/lib/active_record/transactions.rb12
-rw-r--r--activerecord/test/cases/migration/references_foreign_key_test.rb22
-rw-r--r--activesupport/CHANGELOG.md5
-rw-r--r--activesupport/lib/active_support/callbacks.rb34
-rw-r--r--activesupport/test/callbacks_test.rb32
-rw-r--r--guides/source/action_view_overview.md2
-rw-r--r--guides/source/active_support_core_extensions.md47
-rw-r--r--guides/source/active_support_instrumentation.md2
-rw-r--r--guides/source/command_line.md2
-rw-r--r--guides/source/i18n.md2
-rw-r--r--guides/source/initialization.md2
-rw-r--r--guides/source/upgrading_ruby_on_rails.md12
39 files changed, 193 insertions, 130 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 0ae96441ce..4ab0857a66 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,11 @@
+* For actions with no corresponding templates, render `head :no_content`
+ instead of raising an error. This allows for slimmer API controller
+ methods that simply work, without needing further instructions.
+
+ See #19036.
+
+ *Stephen Bussey*
+
* Provide friendlier access to request variants.
request.variant = :phone
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index 59ffb0a19e..13795f0dd8 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -62,9 +62,9 @@ module AbstractController
# using #skip_action_callback
def skip_action_callback(*names)
ActiveSupport::Deprecation.warn('`skip_action_callback` is deprecated and will be removed in the next major version of Rails. Please use skip_before_action, skip_after_action or skip_around_action instead.')
- skip_before_action(*names)
- skip_after_action(*names)
- skip_around_action(*names)
+ skip_before_action(*names, raise: false)
+ skip_after_action(*names, raise: false)
+ skip_around_action(*names, raise: false)
end
def skip_filter(*names)
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index ae04b53825..1573ea7099 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -7,7 +7,12 @@ module ActionController
end
def default_render(*args)
- render(*args)
+ if template_exists?(action_name.to_s, _prefixes, variants: request.variant)
+ render(*args)
+ else
+ logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger
+ head :no_content
+ end
end
def method_for_action(action_name)
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index e30c9c5ade..c98e937423 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -268,7 +268,7 @@ module ActionController
#
# params.permit(:name)
#
- # +:name+ passes it is a key of +params+ whose associated value is of type
+ # +:name+ passes if it is a key of +params+ whose associated value is of type
# +String+, +Symbol+, +NilClass+, +Numeric+, +TrueClass+, +FalseClass+,
# +Date+, +Time+, +DateTime+, +StringIO+, +IO+,
# +ActionDispatch::Http::UploadedFile+ or +Rack::Test::UploadedFile+.
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index fbaa90d521..5a0e5c62e4 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -5,9 +5,9 @@ module ActionController
# 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
# to implement +env+ which needs to be Rack-compatible and +request+
- # which is either instance of +ActionDispatch::Request+ or an object
- # that responds to <tt>host</tt>, <tt>optional_port</tt>, <tt>protocol</tt> and
- # <tt>symbolized_path_parameter</tt> methods.
+ # which is either an instance of +ActionDispatch::Request+ or an object
+ # that responds to the +host+, +optional_port+, +protocol+ and
+ # +symbolized_path_parameter+ methods.
#
# class RootUrl
# include ActionController::UrlFor
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 732ee67268..a1f84e5ace 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -340,7 +340,7 @@ module ActionDispatch
end
protected
- def parse_query(qs)
+ def parse_query(*)
Utils.deep_munge(super)
end
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index 1f5f66dc80..7aef8a50ce 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require "active_support/log_subscriber/test_helper"
class RespondToController < ActionController::Base
layout :set_layout
@@ -608,19 +609,29 @@ class RespondToControllerTest < ActionController::TestCase
end
def test_invalid_variant
+ logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
+ old_logger, ActionController::Base.logger = ActionController::Base.logger, logger
+
@request.variant = :invalid
- assert_raises(ActionView::MissingTemplate) do
- get :variant_with_implicit_rendering
- end
+ get :variant_with_implicit_rendering
+ assert_response :no_content
+ assert_equal 1, logger.logged(:info).select{ |s| s =~ /No template found/ }.size, "Implicit head :no_content not logged"
+ ensure
+ ActionController::Base.logger = old_logger
end
def test_variant_not_set_regular_template_missing
- assert_raises(ActionView::MissingTemplate) do
- get :variant_with_implicit_rendering
- end
+ get :variant_with_implicit_rendering
+ assert_response :no_content
end
def test_variant_with_implicit_rendering
+ @request.variant = :implicit
+ get :variant_with_implicit_rendering
+ assert_response :no_content
+ end
+
+ def test_variant_with_implicit_template_rendering
@request.variant = :mobile
get :variant_with_implicit_rendering
assert_equal "text/html", @response.content_type
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 74a677968f..9d40bd6d5d 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,9 @@
+* `translate` allows `default: [[]]` again for a default value of `[]`.
+
+ Fixes #19640.
+
+ *Adam Prescott*
+
* `translate` should accept nils as members of the `:default`
parameter without raising a translation missing error. Fixes a
regression introduced 362557e.
diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb
index 5c28043f8a..60fc9ee1a2 100644
--- a/actionview/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb
@@ -127,7 +127,7 @@ module ActionView
# auto_discovery_link_tag(:rss, {controller: "news", action: "feed"})
# # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/news/feed" />
# auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"})
- # # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed" />
+ # # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed.rss" />
def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {})
if !(type == :rss || type == :atom) && tag_options[:type].blank?
raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss or :atom.")
diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb
index 29a0860c00..9d7390f1fd 100644
--- a/actionview/lib/action_view/helpers/translation_helper.rb
+++ b/actionview/lib/action_view/helpers/translation_helper.rb
@@ -41,7 +41,7 @@ module ActionView
remaining_defaults = Array(options.delete(:default)).compact
if has_default && !remaining_defaults.first.kind_of?(Symbol)
- options[:default] = remaining_defaults.shift
+ options[:default] = remaining_defaults
end
# If the user has explicitly decided to NOT raise errors, pass that option to I18n.
diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
index 36855ec3d0..4452dcfed5 100644
--- a/actionview/lib/action_view/lookup_context.rb
+++ b/actionview/lib/action_view/lookup_context.rb
@@ -126,7 +126,7 @@ module ActionView
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
end
- def exists?(name, prefixes = [], partial = false, keys = [], options = {})
+ def exists?(name, prefixes = [], partial = false, keys = [], **options)
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys, options))
end
alias :template_exists? :exists?
diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb
index c4daaae221..df096b3c3a 100644
--- a/actionview/test/template/translation_helper_test.rb
+++ b/actionview/test/template/translation_helper_test.rb
@@ -195,6 +195,11 @@ class TranslationHelperTest < ActiveSupport::TestCase
assert_equal 'A Generic String', translation
end
+ def test_translate_with_array_of_array_default
+ translation = translate(:'translations.missing', default: [[]])
+ assert_equal [], translation
+ end
+
def test_translate_does_not_change_options
options = {}
translate(:'translations.missing', options)
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index ae0016d3d5..32a2cb4517 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -40,11 +40,11 @@
cat = Cat.new
cat.assign_attributes(name: "Gorby", status: "yawning")
- cat.name # => 'Gorby'
- cat.status => 'yawning'
+ cat.name # => 'Gorby'
+ cat.status # => 'yawning'
cat.assign_attributes(status: "sleeping")
- cat.name # => 'Gorby'
- cat.status => 'sleeping'
+ cat.name # => 'Gorby'
+ cat.status # => 'sleeping'
*Bogdan Gusiev*
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 176d4c0607..74d60327d6 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -401,7 +401,7 @@ module ActiveModel
protected
def run_validations! #:nodoc:
- _run_validate_callbacks
+ run_callbacks :validate
errors.empty?
end
diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb
index 4b58ef66e3..b4301c23e4 100644
--- a/activemodel/lib/active_model/validations/callbacks.rb
+++ b/activemodel/lib/active_model/validations/callbacks.rb
@@ -109,7 +109,7 @@ module ActiveModel
# Overwrite run validations to include callbacks.
def run_validations! #:nodoc:
- _run_validation_callbacks { super }
+ run_callbacks(:validation) { super }
end
end
end
diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb
index 060919fac3..c22a58f9e1 100644
--- a/activemodel/lib/active_model/validations/length.rb
+++ b/activemodel/lib/active_model/validations/length.rb
@@ -23,7 +23,7 @@ module ActiveModel
if options[:tokenizer]
ActiveSupport::Deprecation.warn(<<-EOS.strip_heredoc)
The `:tokenizer` option is deprecated, and will be removed in Rails 5.1.
- You can achieve the same functionality be defining an instance method
+ You can achieve the same functionality by defining an instance method
with the value that you want to validate the length of. For example,
validates_length_of :essay, minimum: 100,
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 8793d6de70..780c34147d 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Foreign key related methods in the migration DSL respect
+ `ActiveRecord::Base.pluralize_table_names = false`.
+
+ Fixes #19643.
+
+ *Mehmet Emin İNAÇ*
+
* Reduce memory usage from loading types on pg.
Fixes #19578.
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 4897ec44e9..29e8a0edc1 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -135,7 +135,7 @@ module ActiveRecord
if scope.klass.primary_key
count = scope.destroy_all.length
else
- scope.each(&:_run_destroy_callbacks)
+ scope.each { |record| record.run_callbacks :destroy }
arel = scope.arel
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index f44e5af5de..2fcba8e309 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -289,25 +289,24 @@ module ActiveRecord
end
def destroy #:nodoc:
- _run_destroy_callbacks { super }
+ run_callbacks(:destroy) { super }
end
def touch(*) #:nodoc:
- _run_touch_callbacks { super }
+ run_callbacks(:touch) { super }
end
private
-
def create_or_update(*) #:nodoc:
- _run_save_callbacks { super }
+ run_callbacks(:save) { super }
end
def _create_record #:nodoc:
- _run_create_callbacks { super }
+ run_callbacks(:create) { super }
end
def _update_record(*) #:nodoc:
- _run_update_callbacks { super }
+ run_callbacks(:update) { super }
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index d99dc9a5db..8c50f3d1a3 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -358,7 +358,7 @@ module ActiveRecord
synchronize do
owner = conn.owner
- conn._run_checkin_callbacks do
+ conn.run_callbacks :checkin do
conn.expire
end
@@ -449,7 +449,7 @@ module ActiveRecord
end
def checkout_and_verify(c)
- c._run_checkout_callbacks do
+ c.run_callbacks :checkout do
c.verify!
end
c
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index a768ee2d70..cb83d0022c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -138,7 +138,7 @@ module ActiveRecord
end
def foreign_table_name
- name.to_s.pluralize
+ Base.pluralize_table_names ? name.to_s.pluralize : name
end
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 72e019066e..ab1b098e53 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -377,6 +377,9 @@ module ActiveRecord
# [<tt>:force</tt>]
# Set to +:cascade+ to drop dependent objects as well.
# Defaults to false.
+ # [<tt>:if_exists</tt>]
+ # Set to +true+ to only drop the table if it exists.
+ # Defaults to false.
#
# Although this command ignores most +options+ and the block if one is given,
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
@@ -667,7 +670,10 @@ module ActiveRecord
# remove_reference(:products, :user, index: true, foreign_key: true)
#
def remove_reference(table_name, ref_name, options = {})
- remove_foreign_key table_name, ref_name.to_s.pluralize if options[:foreign_key]
+ if options[:foreign_key]
+ reference_name = Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
+ remove_foreign_key(table_name, reference_name)
+ end
remove_column(table_name, "#{ref_name}_id")
remove_column(table_name, "#{ref_name}_type") if options[:polymorphic]
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 b7c7ff1187..22c9076086 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -562,6 +562,21 @@ module ActiveRecord
rename_table_indexes(table_name, new_name)
end
+ # Drops a table from the database.
+ #
+ # [<tt>:force</tt>]
+ # Set to +:cascade+ to drop dependent objects as well.
+ # Defaults to false.
+ # [<tt>:if_exists</tt>]
+ # Set to +true+ to only drop the table if it exists.
+ # Defaults to false.
+ # [<tt>:temporary</tt>]
+ # Set to +true+ to drop temporary table.
+ # Defaults to false.
+ #
+ # Although this command ignores most +options+ and the block if one is given,
+ # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
+ # In that case, +options+ and the block will be used by create_table.
def drop_table(table_name, options = {})
execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
end
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 c048d570e8..168180cfd3 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -87,7 +87,7 @@ module ActiveRecord
SQL
end
- def drop_table(table_name, options = {})
+ 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
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 9b7cba08de..1ad910c4bc 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -302,7 +302,7 @@ module ActiveRecord
assign_attributes(attributes) if attributes
yield self if block_given?
- _run_initialize_callbacks
+ run_callbacks :initialize
end
# Initialize an empty model object from +coder+. +coder+ should be
@@ -329,8 +329,8 @@ module ActiveRecord
self.class.define_attribute_methods
- _run_find_callbacks
- _run_initialize_callbacks
+ run_callbacks :find
+ run_callbacks :initialize
self
end
@@ -366,7 +366,7 @@ module ActiveRecord
@attributes = @attributes.dup
@attributes.reset(self.class.primary_key)
- _run_initialize_callbacks
+ run_callbacks(:initialize)
@new_record = true
@destroyed = false
diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb
index 6b26d7be78..af816a278e 100644
--- a/activerecord/lib/active_record/log_subscriber.rb
+++ b/activerecord/lib/active_record/log_subscriber.rb
@@ -31,9 +31,10 @@ module ActiveRecord
end
def sql(event)
- self.class.runtime += event.duration
return unless logger.debug?
+ self.class.runtime += event.duration
+
payload = event.payload
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
diff --git a/activerecord/lib/active_record/railties/controller_runtime.rb b/activerecord/lib/active_record/railties/controller_runtime.rb
index af4840476c..8727e46cb3 100644
--- a/activerecord/lib/active_record/railties/controller_runtime.rb
+++ b/activerecord/lib/active_record/railties/controller_runtime.rb
@@ -19,7 +19,7 @@ module ActiveRecord
end
def cleanup_view_runtime
- if ActiveRecord::Base.connected?
+ if logger.info? && ActiveRecord::Base.connected?
db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
self.db_runtime = (db_runtime || 0) + db_rt_before_render
runtime = super
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 2293d1b258..311dacb449 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -319,8 +319,8 @@ module ActiveRecord
end
def before_committed! # :nodoc:
- _run_before_commit_without_transaction_enrollment_callbacks
- _run_before_commit_callbacks
+ run_callbacks :before_commit_without_transaction_enrollment
+ run_callbacks :before_commit
end
# Call the +after_commit+ callbacks.
@@ -329,8 +329,8 @@ module ActiveRecord
# but call it after the commit of a destroyed object.
def committed!(should_run_callbacks: true) #:nodoc:
if should_run_callbacks && destroyed? || persisted?
- _run_commit_without_transaction_enrollment_callbacks
- _run_commit_callbacks
+ run_callbacks :commit_without_transaction_enrollment
+ run_callbacks :commit
end
ensure
force_clear_transaction_record_state
@@ -340,8 +340,8 @@ module ActiveRecord
# state should be rolled back to the beginning or just to the last savepoint.
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
if should_run_callbacks
- _run_rollback_without_transaction_enrollment_callbacks
- _run_rollback_callbacks
+ run_callbacks :rollback
+ run_callbacks :rollback_without_transaction_enrollment
end
ensure
restore_transaction_record_state(force_restore_state)
diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb
index 17ac72a109..87348d0f90 100644
--- a/activerecord/test/cases/migration/references_foreign_key_test.rb
+++ b/activerecord/test/cases/migration/references_foreign_key_test.rb
@@ -105,6 +105,28 @@ module ActiveRecord
@connection.remove_reference :testings, :testing_parent, foreign_key: true
end
end
+
+ test "foreign key methods respect pluralize_table_names" do
+ begin
+ original_pluralize_table_names = ActiveRecord::Base.pluralize_table_names
+ ActiveRecord::Base.pluralize_table_names = false
+ @connection.create_table :testing
+ @connection.change_table :testing_parents do |t|
+ t.references :testing, foreign_key: true
+ end
+
+ fk = @connection.foreign_keys("testing_parents").first
+ assert_equal "testing_parents", fk.from_table
+ assert_equal "testing", fk.to_table
+
+ assert_difference "@connection.foreign_keys('testing_parents').size", -1 do
+ @connection.remove_reference :testing_parents, :testing, foreign_key: true
+ end
+ ensure
+ ActiveRecord::Base.pluralize_table_names = original_pluralize_table_names
+ @connection.drop_table "testing", if_exists: true
+ end
+ end
end
end
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 7eaad6340f..3ad2392365 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,8 @@
+* `ActiveSupport::Callbacks#skip_callback` now raises an `ArgumentError` if
+ an unrecognized callback is removed.
+
+ *Iain Beeston*
+
* Added `ActiveSupport::ArrayInquirer` and `Array#inquiry`.
Wrapping an array in an `ArrayInquirer` gives a friendlier way to check its
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 9cf09ab266..814fd288cf 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -80,14 +80,10 @@ module ActiveSupport
# save
# end
def run_callbacks(kind, &block)
- send "_run_#{kind}_callbacks", &block
- end
-
- private
+ callbacks = send("_#{kind}_callbacks")
- def _run_callbacks(callbacks, &block)
if callbacks.empty?
- block.call if block
+ yield if block_given?
else
runner = callbacks.compile
e = Filters::Environment.new(self, false, nil, block)
@@ -95,6 +91,8 @@ module ActiveSupport
end
end
+ private
+
# A hook invoked every time a before callback is halted.
# This can be overridden in AS::Callback implementors in order
# to provide better debugging/logging.
@@ -691,19 +689,27 @@ module ActiveSupport
# class Writer < Person
# skip_callback :validate, :before, :check_membership, if: -> { self.age > 18 }
# end
+ #
+ # An <tt>ArgumentError</tt> will be raised if the callback has not
+ # already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
def skip_callback(name, *filter_list, &block)
type, filters, options = normalize_callback_params(filter_list, block)
+ options[:raise] = true unless options.key?(:raise)
__update_callbacks(name) do |target, chain|
filters.each do |filter|
- filter = chain.find {|c| c.matches?(type, filter) }
+ callback = chain.find {|c| c.matches?(type, filter) }
+
+ if !callback && options[:raise]
+ raise ArgumentError, "#{type.to_s.capitalize} #{name} callback #{filter.inspect} has not been defined"
+ end
- if filter && options.any?
- new_filter = filter.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless])
- chain.insert(chain.index(filter), new_filter)
+ if callback && (options.key?(:if) || options.key?(:unless))
+ new_callback = callback.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless])
+ chain.insert(chain.index(callback), new_callback)
end
- chain.delete(filter)
+ chain.delete(callback)
end
target.set_callbacks name, chain
end
@@ -800,12 +806,6 @@ module ActiveSupport
names.each do |name|
class_attribute "_#{name}_callbacks"
set_callbacks name, CallbackChain.new(name, options)
-
- module_eval <<-RUBY, __FILE__, __LINE__ + 1
- def _run_#{name}_callbacks(&block)
- _run_callbacks(_#{name}_callbacks, &block)
- end
- RUBY
end
end
diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb
index f6abef8cee..cda9732cae 100644
--- a/activesupport/test/callbacks_test.rb
+++ b/activesupport/test/callbacks_test.rb
@@ -73,8 +73,8 @@ module CallbacksTest
class PersonSkipper < Person
skip_callback :save, :before, :before_save_method, :if => :yes
- skip_callback :save, :after, :before_save_method, :unless => :yes
- skip_callback :save, :after, :before_save_method, :if => :no
+ skip_callback :save, :after, :after_save_method, :unless => :yes
+ skip_callback :save, :after, :after_save_method, :if => :no
skip_callback :save, :before, :before_save_method, :unless => :no
skip_callback :save, :before, CallbackClass , :if => :yes
def yes; true; end
@@ -1021,7 +1021,7 @@ module CallbacksTest
define_callbacks :foo
n.times { set_callback :foo, :before, callback }
def run; run_callbacks :foo; end
- def self.skip(thing); skip_callback :foo, :before, thing; end
+ def self.skip(*things); skip_callback :foo, :before, *things; end
}
end
@@ -1070,11 +1070,11 @@ module CallbacksTest
}
end
- def test_skip_lambda # removes nothing
+ def test_skip_lambda # raises error
calls = []
callback = ->(o) { calls << o }
klass = build_class(callback)
- 10.times { klass.skip callback }
+ assert_raises(ArgumentError) { klass.skip callback }
klass.new.run
assert_equal 10, calls.length
end
@@ -1088,11 +1088,29 @@ module CallbacksTest
assert_equal 0, calls.length
end
- def test_skip_eval # removes nothing
+ def test_skip_string # raises error
calls = []
klass = build_class("bar")
klass.class_eval { define_method(:bar) { calls << klass } }
- klass.skip "bar"
+ assert_raises(ArgumentError) { klass.skip "bar" }
+ klass.new.run
+ assert_equal 1, calls.length
+ end
+
+ def test_skip_undefined_callback # raises error
+ calls = []
+ klass = build_class(:bar)
+ klass.class_eval { define_method(:bar) { calls << klass } }
+ assert_raises(ArgumentError) { klass.skip :qux }
+ klass.new.run
+ assert_equal 1, calls.length
+ end
+
+ def test_skip_without_raise # removes nothing
+ calls = []
+ klass = build_class(:bar)
+ klass.class_eval { define_method(:bar) { calls << klass } }
+ klass.skip :qux, raise: false
klass.new.run
assert_equal 1, calls.length
end
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md
index 71f3f8882c..02ef32d66e 100644
--- a/guides/source/action_view_overview.md
+++ b/guides/source/action_view_overview.md
@@ -408,7 +408,7 @@ Returns a link tag that browsers and feed readers can use to auto-detect an RSS
```ruby
auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", { title: "RSS Feed" }) # =>
- <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="http://www.example.com/feed" />
+ <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="http://www.example.com/feed.rss" />
```
#### image_path
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 5fb577e256..ff60f95a2c 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -3040,53 +3040,6 @@ The method `Range#overlaps?` says whether any two given ranges have non-void int
NOTE: Defined in `active_support/core_ext/range/overlaps.rb`.
-Extensions to `Proc`
---------------------
-
-### `bind`
-
-As you surely know Ruby has an `UnboundMethod` class whose instances are methods that belong to the limbo of methods without a self. The method `Module#instance_method` returns an unbound method for example:
-
-```ruby
-Hash.instance_method(:delete) # => #<UnboundMethod: Hash#delete>
-```
-
-An unbound method is not callable as is, you need to bind it first to an object with `bind`:
-
-```ruby
-clear = Hash.instance_method(:clear)
-clear.bind({a: 1}).call # => {}
-```
-
-Active Support defines `Proc#bind` with an analogous purpose:
-
-```ruby
-Proc.new { size }.bind([]).call # => 0
-```
-
-As you see that's callable and bound to the argument, the return value is indeed a `Method`.
-
-NOTE: To do so `Proc#bind` actually creates a method under the hood. If you ever see a method with a weird name like `__bind_1256598120_237302` in a stack trace you know now where it comes from.
-
-Action Pack uses this trick in `rescue_from` for example, which accepts the name of a method and also a proc as callbacks for a given rescued exception. It has to call them in either case, so a bound method is returned by `handler_for_rescue`, thus simplifying the code in the caller:
-
-```ruby
-def handler_for_rescue(exception)
- _, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
- ...
- end
-
- case rescuer
- when Symbol
- method(rescuer)
- when Proc
- rescuer.bind(self)
- end
-end
-```
-
-NOTE: Defined in `active_support/core_ext/proc.rb`.
-
Extensions to `Date`
--------------------
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index 352da43b5f..1b14bedfbf 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -19,7 +19,7 @@ After reading this guide, you will know:
Introduction to instrumentation
-------------------------------
-The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the Rails framework, as described below in (TODO: link to section detailing each hook point). With this API, developers can choose to be notified when certain events occur inside their application or another piece of Ruby code.
+The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the [Rails framework](#rails-framework-hooks). With this API, developers can choose to be notified when certain events occur inside their application or another piece of Ruby code.
For example, there is a hook provided within Active Record that is called every time Active Record uses an SQL query on a database. This hook could be **subscribed** to, and used to track the number of queries during a certain action. There's another hook around the processing of an action of a controller. This could be used, for instance, to track how long a specific action has taken.
diff --git a/guides/source/command_line.md b/guides/source/command_line.md
index b409f20122..3bd84b1ce6 100644
--- a/guides/source/command_line.md
+++ b/guides/source/command_line.md
@@ -470,7 +470,7 @@ app/models/article.rb:
NOTE. When using specific annotations and custom annotations, the annotation name (FIXME, BUG etc) is not displayed in the output lines.
-By default, `rake notes` will look in the `app`, `config`, `lib`, `bin` and `test` directories. If you would like to search other directories, you can provide them as a comma separated list in an environment variable `SOURCE_ANNOTATION_DIRECTORIES`.
+By default, `rake notes` will look in the `app`, `config`, `db`, `lib` and `test` directories. If you would like to search other directories, you can provide them as a comma separated list in an environment variable `SOURCE_ANNOTATION_DIRECTORIES`.
```bash
$ export SOURCE_ANNOTATION_DIRECTORIES='spec,vendor'
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index e8d0a83dd0..27f11ebbee 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -201,7 +201,7 @@ end
If your application includes a locale switching menu, you would then have something like this in it:
```ruby
-link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['REQUEST_URI']}")
+link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['PATH_INFO']}")
```
assuming you would set `APP_CONFIG[:deutsch_website_url]` to some value like `http://www.application.de`.
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index 8fbb234698..c0c8b7d4b6 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -163,7 +163,7 @@ throwing an error message. If the command is valid, a method of the same name
is called.
```ruby
-COMMAND_WHITELIST = %(plugin generate destroy console server dbconsole application runner new version help)
+COMMAND_WHITELIST = %w(plugin generate destroy console server dbconsole application runner new version help)
def run_command!(command)
command = parse_command(command)
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 5a6f267360..7666601bd7 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -77,18 +77,20 @@ See [#17227](https://github.com/rails/rails/pull/17227) for more details.
### ActiveJob jobs now inherent from ApplicationJob by default
-In Rails 4.2 an ActiveJob inherents from `ActiveJob::Base`. In Rails 5.0 this
-behaviour has changed to now inherent from `ApplicationJob`.
+In Rails 4.2 an ActiveJob inherits from `ActiveJob::Base`. In Rails 5.0 this
+behavior has changed to now inherit from `ApplicationJob`.
-When upgrading from Rails 4.2 to Rails 5.0 you need to create a file
-`application_job.rb` in `app/jobs/` and add the following content:
+When upgrading from Rails 4.2 to Rails 5.0 you need to create an
+`application_job.rb` file in `app/jobs/` and add the following content:
```
class ApplicationJob < ActiveJob::Base
end
```
-See [#19034](https://github.com/rails/rails/pull/19034) for more details
+Then make sure that all your job classes inherit from it.
+
+See [#19034](https://github.com/rails/rails/pull/19034) for more details.
Upgrading from Rails 4.1 to Rails 4.2
-------------------------------------