Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ nav_order: 6

## main

* Keep compensating ERB line numbers for the annotation newline on future major Rails versions. The version check required a minor version above 0, so it would have stopped compensating on the next major's `.0` release.

*Clément Joubert*

## 4.23.0

* Restore request-dependent URL generation when using `render_preview` inside `with_request_url`.
Expand Down
6 changes: 5 additions & 1 deletion lib/view_component/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ class Template
DEFAULT_FORMAT = :html
private_constant :DEFAULT_FORMAT

# Rails 8.1 added a newline to compiled ERB output (rails/rails#53731).
ERB_NEWLINE_RAILS_VERSION = Gem::Version.new("8.1.0.alpha")
private_constant :ERB_NEWLINE_RAILS_VERSION

DataWithSource = Struct.new(:format, :identifier, :short_identifier, :type)

attr_reader :details, :path
Expand Down Expand Up @@ -209,7 +213,7 @@ def normalized_variant_name
attr_reader :lineno

def erb_newline_compensation_needed?
Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0 &&
Rails.gem_version >= ERB_NEWLINE_RAILS_VERSION &&
details.handler == :erb &&
annotated?
end
Expand Down
6 changes: 3 additions & 3 deletions test/sandbox/test/inline_template_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def call
# is enabled. This test verifies that components can be compiled and rendered when
# coverage is running.
test "file-based templates compile without segfault when coverage is running" do
skip unless Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0
skip unless Rails.gem_version >= Gem::Version.new("8.1.0.alpha")

with_new_cache do
with_coverage_running do
Expand All @@ -267,7 +267,7 @@ def call
# Regression test for segfault when coverage is running but annotations are DISABLED.
# This is the common case in CI environments.
test "file-based templates compile without segfault when coverage is running and annotations disabled" do
skip unless Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0
skip unless Rails.gem_version >= Gem::Version.new("8.1.0.alpha")

without_template_annotations do
with_coverage_running do
Expand All @@ -284,7 +284,7 @@ def call
end

test "inline templates compile without segfault when coverage is running" do
skip unless Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0
skip unless Rails.gem_version >= Gem::Version.new("8.1.0.alpha")

with_new_cache do
with_coverage_running do
Expand Down
4 changes: 2 additions & 2 deletions test/sandbox/test/rendering_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ def test_backtrace_returns_correct_file_and_line_number
render_inline(ExceptionInTemplateComponent.new)
end

component_error_index = (Rails::VERSION::STRING < "8.0") ? 0 : 1
component_error_index = (Rails::VERSION::MAJOR < 8) ? 0 : 1
assert_match %r{app/components/exception_in_template_component\.html\.erb:2}, error.backtrace[component_error_index]
end

Expand All @@ -652,7 +652,7 @@ def test_backtrace_returns_correct_file_and_line_number_in_slim
render_inline(ExceptionInSlimTemplateComponent.new)
end

component_error_index = (Rails::VERSION::STRING < "8.0") ? 0 : 1
component_error_index = (Rails::VERSION::MAJOR < 8) ? 0 : 1
assert_match %r{app/components/exception_in_slim_template_component\.html\.slim:2}, error.backtrace[component_error_index]
end

Expand Down
36 changes: 35 additions & 1 deletion test/sandbox/test/template_annotation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class TemplateAnnotationTest < ViewComponent::TestCase
# conditions, otherwise backtraces point at the wrong line and, when coverage
# is running, template source is stripped away.
def setup
skip unless Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0
skip unless Rails.gem_version >= Gem::Version.new("8.1.0.alpha")
end

def teardown
Expand Down Expand Up @@ -72,3 +72,37 @@ def with_coverage_running
Coverage.result unless already_running
end
end

# The version check doesn't depend on the installed Rails, so it runs on every
# version, unlike the tests above.
class TemplateAnnotationRailsVersionTest < ActiveSupport::TestCase
def test_line_numbers_are_compensated_on_later_major_versions
template = ViewComponent::Template::File.new(
component: RaisingFormatsComponent,
details: ActionView::TemplateDetails.new(nil, :erb, :html, nil),
path: "#{Rails.root}/app/components/raising_formats_component.html.erb"
)

with_rails_version("9.0.0") { assert template.send(:erb_newline_compensation_needed?) }
with_rails_version("8.0.3") { refute template.send(:erb_newline_compensation_needed?) }
end

private

def with_rails_version(version)
major, minor = version.split(".").map(&:to_i)
original = {MAJOR: Rails::VERSION::MAJOR, MINOR: Rails::VERSION::MINOR, STRING: Rails::VERSION::STRING}

replace_version_constants(MAJOR: major, MINOR: minor, STRING: version)
yield
ensure
replace_version_constants(**original)
end

def replace_version_constants(**constants)
constants.each do |name, value|
Rails::VERSION.send(:remove_const, name)
Rails::VERSION.const_set(name, value)
end
end
end
Loading