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.
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 %>
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