1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Deprecate alias_method_chain in favour of Module#prepend

…as discussed #19413
This commit is contained in:
Kir Shatrov 2015-03-20 23:23:41 +02:00
parent cdbe4fd093
commit a982a42d76
7 changed files with 158 additions and 116 deletions

View file

@ -1,3 +1,7 @@
* Deprecate `alias_method_chain` in favour of `Module#prepend` introduced in Ruby 2.0
*Kir Shatrov*
* Added `#without` on `Enumerable` and `Array` to return a copy of an
enumerable without the specified elements.

View file

@ -21,6 +21,8 @@ class Module
#
# so you can safely chain foo, foo?, foo! and/or foo= with the same feature.
def alias_method_chain(target, feature)
ActiveSupport::Deprecation.warn("alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super.")
# Strip out punctuation on predicates, bang or writer methods since
# e.g. target?_without_feature is not a valid method name.
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1

View file

@ -1,18 +1,22 @@
require 'active_support/core_ext/module/aliasing'
class Range #:nodoc:
def each_with_time_with_zone(&block)
ensure_iteration_allowed
each_without_time_with_zone(&block)
end
alias_method_chain :each, :time_with_zone
# TODO: change to Module#prepend as soon as the fix is backported to MRI 2.2:
# https://bugs.ruby-lang.org/issues/10847
alias_method :each_without_time_with_zone, :each
alias_method :each, :each_with_time_with_zone
def step_with_time_with_zone(n = 1, &block)
ensure_iteration_allowed
step_without_time_with_zone(n, &block)
end
alias_method_chain :step, :time_with_zone
# TODO: change to Module#prepend as soon as the fix is backported to MRI 2.2:
# https://bugs.ruby-lang.org/issues/10847
alias_method :step_without_time_with_zone, :step
alias_method :step, :step_with_time_with_zone
private
def ensure_iteration_allowed

View file

@ -1,5 +1,3 @@
require 'active_support/core_ext/module/aliasing'
class Range
# Extends the default Range#include? to support range comparisons.
# (1..5).include?(1..5) # => true
@ -18,6 +16,8 @@ class Range
include_without_range?(value)
end
end
alias_method_chain :include?, :range
# TODO: change to Module#prepend as soon as the fix is backported to MRI 2.2:
# https://bugs.ruby-lang.org/issues/10847
alias_method :include_without_range?, :include?
alias_method :include?, :include_with_range?
end

View file

@ -31,12 +31,14 @@ module ActiveSupport
method_names += options.keys
method_names.each do |method_name|
target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
target_module.send(:define_method, "#{target}_with_deprecation#{punctuation}") do |*args, &block|
mod = Module.new do
define_method(method_name) do |*args, &block|
deprecator.deprecation_warning(method_name, options[method_name])
send(:"#{target}_without_deprecation#{punctuation}", *args, &block)
end
end
super(*args, &block)
end
end
target_module.prepend(mod)
end
end
end

View file

@ -358,7 +358,22 @@ class MethodAliasingTest < ActiveSupport::TestCase
Object.instance_eval { remove_const :FooClassWithBarMethod }
end
def test_alias_method_chain_deprecated
assert_deprecated(/alias_method_chain/) do
Module.new do
def base
end
def base_with_deprecated
end
alias_method_chain :base, :deprecated
end
end
end
def test_alias_method_chain
assert_deprecated(/alias_method_chain/) do
assert @instance.respond_to?(:bar)
feature_aliases = [:bar_with_baz, :bar_without_baz]
@ -377,8 +392,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'bar_with_baz', @instance.bar
assert_equal 'bar', @instance.bar_without_baz
end
end
def test_alias_method_chain_with_punctuation_method
assert_deprecated(/alias_method_chain/) do
FooClassWithBarMethod.class_eval do
def quux!; 'quux' end
end
@ -393,8 +410,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'quux_with_baz', @instance.quux!
assert_equal 'quux', @instance.quux_without_baz!
end
end
def test_alias_method_chain_with_same_names_between_predicates_and_bang_methods
assert_deprecated(/alias_method_chain/) do
FooClassWithBarMethod.class_eval do
def quux!; 'quux!' end
def quux?; true end
@ -423,8 +442,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234)
assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234)
end
end
def test_alias_method_chain_with_feature_punctuation
assert_deprecated(/alias_method_chain/) do
FooClassWithBarMethod.class_eval do
def quux; 'quux' end
def quux?; 'quux?' end
@ -440,8 +461,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
FooClassWithBarMethod.alias_method_chain :quux?, :baz!
end
end
end
def test_alias_method_chain_yields_target_and_punctuation
assert_deprecated(/alias_method_chain/) do
args = nil
FooClassWithBarMethod.class_eval do
@ -457,8 +480,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'quux', args[0]
assert_equal '?', args[1]
end
end
def test_alias_method_chain_preserves_private_method_status
assert_deprecated(/alias_method_chain/) do
FooClassWithBarMethod.class_eval do
def duck; 'duck' end
include BarMethodAliaser
@ -473,8 +498,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'duck_with_orange', @instance.instance_eval { duck }
assert FooClassWithBarMethod.private_method_defined?(:duck)
end
end
def test_alias_method_chain_preserves_protected_method_status
assert_deprecated(/alias_method_chain/) do
FooClassWithBarMethod.class_eval do
def duck; 'duck' end
include BarMethodAliaser
@ -489,8 +516,10 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'duck_with_orange', @instance.instance_eval { duck }
assert FooClassWithBarMethod.protected_method_defined?(:duck)
end
end
def test_alias_method_chain_preserves_public_method_status
assert_deprecated(/alias_method_chain/) do
FooClassWithBarMethod.class_eval do
def duck; 'duck' end
include BarMethodAliaser
@ -501,6 +530,7 @@ class MethodAliasingTest < ActiveSupport::TestCase
assert_equal 'duck_with_orange', @instance.duck
assert FooClassWithBarMethod.public_method_defined?(:duck)
end
end
def test_delegate_with_case
event = Event.new(Tester.new)

View file

@ -506,6 +506,8 @@ Extensions to `Module`
### `alias_method_chain`
**This method is deprecated in favour of using Module#prepend.**
Using plain Ruby you can wrap methods with other methods, that's called _alias chaining_.
For example, let's say you'd like params to be strings in functional tests, as they are in real requests, but still want the convenience of assigning integers and other kind of values. To accomplish that you could wrap `ActionController::TestCase#process` this way in `test/test_helper.rb`:
@ -550,8 +552,6 @@ ActionController::TestCase.class_eval do
end
```
Rails uses `alias_method_chain` all over the code base. For example validations are added to `ActiveRecord::Base#save` by wrapping the method that way in a separate module specialized in validations.
NOTE: Defined in `active_support/core_ext/module/aliasing.rb`.
### Attributes