Ruby on Rails | Hotwire | RubyUI - How to solve performance issues when expanding a form details within a list of forms

Ruby on Rails | Hotwire | RubyUI - How to solve performance issues when expanding a form details within a list of forms

The final result is highly practical, reactive, performant, and functional.

Article content
Final result

Consider a scenario where you have a list of forms, as illustrated in the image below.

Article content
Forms list

And for each completed form, you can view the details in a side modal, without needing to navigate to the form's detail page.

Article content
Form details

Considering that a user may have multiple forms, and each form needs to load several questions and answers from the database to display the final result, it’s crucial that we avoid running a single, heavy query that loads a massive amount of HTML—most of which the user likely won’t even see.

The solution to this problem is quite simple and straightforward.

We need to open the side modal at the moment the user clicks the preview button, send a request to Rails with the selected document’s ID, and use TURBO_STREAM to update the content of the side modal.

Let’s implement the solution.

The first step is to define the route and the controller behavior triggered by the user’s click.

# config/routes.rb
resources :documents, only: %i[index show], shallow: true do
  get :preview_sheet
end

# buyers/documents_controller.rb
def preview_sheet
  @document = Document.find(params[:document_id])
  authorize!(@document, to: :show?, with: ::Ssr::DocumentPolicy)
end

# buyers/documents/preview_sheet.turbo_stream.erb
<%= turbo_stream.update("PREVIEW_SHEET") do %>
  <%= render(Buyers::Documents::PreviewSheet::Information.new(document: @document)) %>
<% end %>        

The second step is to display the side modal with a generic loading indicator—or, in this case, I implemented a skeleton loader, as it provides a more modern and visually appealing experience.

Article content
Loading form details

The RubyUI code below is responsible for opening the side modal, but there are a few important points to clarify before diving into the code itself.

First, it's necessary to add data_turbo_stream="true" to the HTML element, as we won’t be updating the entire page with the request—only the content of the side modal.

Second, we need to assign an id to the div that will be updated via TURBO_STREAM. In this case, I used 'PREVIEW_SHEET'.

# buyers/documents/preview_sheet.rb
Sheet do
  SheetTrigger do
    href = buyers_document_preview_sheet_path(@form_group)

    Link(href:, variant: "ghost", class: "p-1 size-fit", data: {turbo_stream: true}) do
      lucide_icon("eye", class: "size-4 flex-none text-primary")
    end
  end

  SheetContent(class: "w-full max-w-xl") do
    div(id: "PREVIEW_SHEET") do
      10.times do
        div(class: "my-4 w-full h-8 animate-pulse rounded-md bg-muted")
      end
    end
  end
end        

The third step is to populate the document data in the side modal.

# buyers/documents/preview_sheet/information.rb
SheetHeader do
  href = edit_buyers_form_groups_override_path(@document)

  div(class: "mt-6 flex flex-row items-center justify-between gap-3") do
    SheetTitle { @document.display_name }
    Link(href:, variant: "outline") { "Edit" }
  end
end

SheetMiddle do
  # ... SHEET CONTENT HERE ...
end        

Thanks a lot for reading it!


To view or add a comment, sign in

More articles by Jean Pierry

Insights from the community

Others also viewed

Explore topics