Weird Rails partials bug with View Components

Content rendered outside partials with View Components helpers

Yesterday, during my regular Avo coding sessions I ran into a strange-looking bug.

Context

I created a View Component names ResourceShow inside which I used a helper a_link that renders a button-looking link using a helper and a regular Rails partial. The code looks like this:

# application_helper.rb
module ApplicationHelper
  def a_link(label, url = nil, **args, &block)
    args[:style] = 'border: 1px solid red;'

    if block_given?
      url = label
    end

    locals = {
      label: label,
      url: url,
      args: args,
    }

    if block_given?
      render layout: 'layouts/a_link', locals: locals do
        capture(&block)
      end
    else
      render partial: 'layouts/a_link', locals: locals
    end
  end
end
# application_helper.rb
<% if (block = yield).empty? %>
  <%= link_to label, url, **args %>
<% else %>
  <%= link_to url, **args do %>
    <%= yield %>
  <% end %>
<% end %>

So running this <%= a_link '/' do %>Content inside the button<% end %> should render a basic button. Because we'll be using this helper inside a view component, by checking their docs on helpers we need to prepend the helpers. function, so we'll do <%= helpers.a_link '/' do %>Content inside the button<% end %>.

But instead of our plain button, we'll get this weird bug.

image.png

The content inside the block will get duplicated and prepended outside the whole button 🤯

The fix

You just need to stop using the helpers prepend method in the template and include the helper module in the view component 🔥.

# app/components/hello_component.rb
class HelloComponent < ViewComponent::Base
  include ApplicationHelper
end
# app/components/hello_component.html.erb
<%= a_link '/' do %>
  Content inside the button
<% end %>

image.png

I'm writing this hoping that this will help someone in the future not lose their minds with this weird partials bug.

Stay sane, stay positive ✌️

Photo by Greta Pichetti

Source code on GitHub

No Comments Yet