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