Is it a good idea to handle code logic in views/partials? (Maintainability vs Performance)

I’m pretty sure this may have been answered 5 or 10 years ago but given it’s 2024 and Rails 7.1 Hotwire era I would like to hear your opinion. So please hear me out:

Recently I’ve tried component based libraries like ViewComponent, Phlex and I see why devs like them = the code logic is close to HTML = less of a mess when complex view logic is required (same reasons why React Components are loved) .

But to be honest the more I’ve implemented these component gems in my personal projects less “Rails-like” those applications felt = I was over-abstracting most of ordinary things for no good reason.

So I’ve circled back to way how I would write views 15y ago where I would mix code logic and HTML directly in ERB view/partial. Here is an example what I mean:

<!-- app/views/comments/_comment.html.erb -->
<%
avatar = comment.user.avatar.variant(resize_to_fill: [300, 300])
something_complex_to_calc = comment.user.articles.where(whatever: "complex").order(id: :desc).count
user_name = comment.user.want_to_stay_annonymus? ? "Another User" : comment.user.name
%>
<%= turbo_frame_tag comment do %>
  <div class="p-3 flex justify-between">
    <%= image_tag avatar, class: "mr-2" %>
    <div>
      <p class="pb-2">
        <%= truncate comment.body, length: 255 %>
      <small class="font-semibold text-gray-500"><%= user_name %> (<%= something_complex_to_calc %>)</small> - <%= time_ago_in_words(comment.created_at) %> 
    </div>
  <div>
<% end %>

:point_up: I feel everything components have to offer from maintainability perspective can be achieved with Rails views/partials . I’m writing every personal project this way and I’m impressed how obviously productive and maintainable this is. (Given I try to keep small CRUD controllers supported by Hotwire)

My question is: is this a good idea? I’m worried about long term performance.

But Given I have good Russian doll caching practices I believe this shouldn’t be an issue :thinking: But even if they are not cached is this big deal in 2024 ? (Ruby 3.3 fast, Rails fast :person_shrugging:)

What do you think? Any better ideas? Thank you

@DHH if you find the time, I would love to hear your opinion too pretty please :pray:

P.S. And yes there are always ViewObjects, Presenters, FormObjects,… but my opinion is those should be reserved for “there’s no other way out” situations. I’m more concerned about 95% of app views

6 Likes

As someone who actually gives a damn about how my sites appear to those visitors* who can’t or don’t want to execute my client side code I’m a big fan of the .erb partial method. Complex logic goes elsewhere (that’s what view helpers are for), but simple inline if this then that type logic sits comfortably in partials imo. I’m also a big fan of collection: parials, and using locals: to make the partials portable. With .erb partials the exact same code can be used to serve components over XHR as would be used for a regular HTTP get. It’s as “railsy” as can be, works well with fragment/russian-doll caching, and the code is easy to read also for developers who aren’t familiar with LibraryX.JS. I honestly struggle to see what was so wrong with it in the first place? Seems like a “fix until it’s broken” thing.

*) carbon or silicon based alike - both able bodied and less so!

I would create small helpers methods (in /app/helpers) for few reasons:

  • I really prefer the logic to be outside of the view. The view is to show, not calculate.
  • If/when there’s a performance issue, with a separated method it will be shown in the right tool (AppSignal, NewRelic, …)
  • With enough time, it will be re-use somewhere else
1 Like

Ok. But isn’t it still true that ViewComponents/Phlex render much faster?

If you’re talking about maintainability/readability of ViewComponents, I agree that they feel overly scattered and bureaucratic. Like GraphQL, the whole code pattern seems to assume the existence of a large team.

But my feeling is that a Phlex component is a lot easier to read, and just as maintainable as an erb template. Also, it’s a real issue when Views do too much logic, the logic is not easy to test. I’ve been bitten by that recently.

Irrelevante.

If you look at the overall request time, it’s very unlike that the view, any view, is the bottleneck. You need to benchmark the entire request and see the difference between 2 implementations. Usually you better spend your time around database access for the most improvement returns.

1 Like

“any view” is probably not the right wording here. I remember very well when switching from HAML to HAMLit or SLIME (different projects) made a rather sizeable change for me with complex views.

At that moment in time (many years ago): yes. Now: no. HAMLit has been merged to HAML 5.

Today: Slim, HAML and ERB have a very similar performance that it is mostly a personal preference and legacy reasons.

In fact in doesn’t look like HAMLit was “merged to HAML 5”. Apparently its implementation’s been copied over to HAML 6 (not 5) instead. HAML 6 OTOH was released on 2022-09-21. I guess in the times of AI development those 18 months may indeed qualify as “many years ago” :wink: Anyway - thank you for pointing out. I didn’t follow HAML development since switched to HAMLit back then.

Thank you to point out my mistake about HAMLit and HAML 6. I know about it because I took over an old app and upgrade all dependencies. Also took a look at latest version of gems that was old-ish release and found hamlit recommending haml instead (in the readme)

1 Like