Skip to content

@view_context set too late #2482

@23tux

Description

@23tux

Steps to reproduce

Two components, one renders the other:

class TestComponent < ViewComponent::Base
  def call
    render(Test2Component.new)
  end
end

class Test2Component < ViewComponent::Base
  def render?
    t(".foo")
  end

  def call
    "That's test 2!"
  end
end
# en.yml
test_component2:
  foo: Foobar
<%= render(TestComponent.new) %>

This throws an error:

Translation missing: en.test_component.foo

Expected behavior

It should use the Test2Component's virtual path.

Actual behavior

It uses the parent's virtual path: When nested component is rendered, and inside it's render? method a t("...") is called, it seems to still have the @virtual_path of it's parent component:

From: /usr/src/app/app/components/test2_component.rb:6 Test2Component#render?:

    4: def render?
    5:   binding.pry
 => 6:   t(".foo")
    7: end

[5] pry(#<Test2Component>)> @virtual_path
=> "test2_component"
[6] pry(#<Test2Component>)> @view_context.instance_variable_get(:@virtual_path)
=> "test_component"

My guess is, that the @virtual_path of the @view_context is set too late:

if render?
value = nil
@output_buffer.with_buffer do
@view_context.instance_variable_set(:@virtual_path, virtual_path)

Would it be possible, to move the line @view_context.instance_variable_set(:@virtual_path, virtual_path) above the render? check? Or is this going to break other things?

Backtrace:

  1) TestComponent
     Failure/Error: super

     I18n::MissingTranslationData:
       Translation missing: en.test_component.foo
     # /usr/local/bundle/gems/i18n-1.14.1/lib/i18n.rb:394:in `handle_exception'
     # /usr/local/bundle/gems/i18n-1.14.1/lib/i18n.rb:367:in `translate_key'
     # ./spec/rails_helper.rb:103:in `translate_key'
     # /usr/local/bundle/gems/i18n-1.14.1/lib/i18n.rb:222:in `translate'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/translatable.rb:96:in `translate'
     # ./app/components/test2_component.rb:5:in `render?'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:138:in `render_in'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:261:in `render'
     # ./app/components/test_component.rb:5:in `call'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/template.rb:85:in `block in safe_method_name_call'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/compiler.rb:91:in `instance_exec'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/compiler.rb:91:in `block in define_render_template_for'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:146:in `block (2 levels) in render_in'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:237:in `around_render'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:145:in `block in render_in'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:23:in `with_buffer'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/base.rb:141:in `render_in'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/test_helpers.rb:41:in `render_inline'
     # ./spec/components/test_component_spec.rb:7:in `block (2 levels) in <main>'
     # ./spec/components/test_component_spec.rb:15:in `block (2 levels) in <main>'
     # ./spec/rails_helper.rb:185:in `block (3 levels) in <main>'
     # /usr/local/bundle/gems/view_component-4.1.0/lib/view_component/test_helpers.rb:152:in `with_controller_class'
     # ./spec/rails_helper.rb:184:in `block (2 levels) in <main>'

System configuration

Rails version: 7.1

Ruby version: 3.3.3

Gem version: 4.1.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions