Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect line number if a helper_method raises #45116

Merged
merged 1 commit into from May 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions actionpack/lib/abstract_controller/helpers.rb
Expand Up @@ -84,10 +84,13 @@ def helper_method(*methods)
file, line = location.path, location.lineno

methods.each do |method|
_helpers_for_modification.class_eval <<~ruby_eval, file, line
def #{method}(*args, &block) # def current_user(*args, &block)
controller.send(:'#{method}', *args, &block) # controller.send(:'current_user', *args, &block)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds a lot like Module#delegate, can't we call that instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually nevermind, delegate wouldn't allow to pass the source location, and also does some extra things we don't need.

end # end
# def current_user(*args, &block)
# controller.send(:'current_user', *args, &block)
# end
_helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
def #{method}(*args, &block)
controller.send(:'#{method}', *args, &block)
end
ruby2_keywords(:'#{method}')
ruby_eval
end
Expand Down
13 changes: 13 additions & 0 deletions actionpack/test/controller/helper_test.rb
Expand Up @@ -98,6 +98,9 @@ class TestController < ActionController::Base
def delegate_method() end
def delegate_method_arg(arg); arg; end
def delegate_method_kwarg(hi:); hi; end
def method_that_raises
raise "an error occurred"
end
end

def setup
Expand Down Expand Up @@ -145,6 +148,16 @@ def test_helper_method_kwarg
assert_equal(:there, @controller_class.new.helpers.delegate_method_kwarg(hi: :there))
end

def test_helper_method_with_error_has_correct_backgrace
@controller_class.helper_method :method_that_raises
expected_backtrace_pattern = "#{__FILE__}:#{__LINE__ - 1}"

error = assert_raises(RuntimeError) do
@controller_class.new.helpers.method_that_raises
end
assert_not_nil error.backtrace.find { |line| line.include?(expected_backtrace_pattern) }
end

def test_helper_attr
assert_nothing_raised { @controller_class.helper_attr :delegate_attr }
assert_includes master_helper_methods, :delegate_attr
Expand Down