Search code examples
ruby-on-railsrubyturbolinksruby-on-rails-7turbo

Rails 7 + Turbo: turbo_stream respond with extra data on partial template?


Im playing around Rails 7 + Turbo and I'm trying to create a form which has a dropdown of user lists. The form could create a new "Unit" record and assign users to this unit. The plan create a dropdown where you can search and select the owner of the unit record. The problem is turbo stream returns an extra data(the collection). I've checked the network request and apparently, the back-end is sending this template with extra data. How do i create a response without this extra data and just return the partial template?

the extra data

[#<User id: 4, email: "[email protected]", created_at: "2022-03-18 13:29:04.813660000 +0000", updated_at: "2022-03-18 13:29:19.397311000 +0000", first_name: nil, last_name: nil, phone: nil, meta: {}, account_id: 2>]

and this is the full response.

<turbo-stream action="update" target="owner_search_result"><template>
    <li
      id=user_4
      class="hover:bg-blue-600 relative select-none py-2 pl-3 pr-9 text-gray-900 cursor-pointer" id="option-0"
      role="option" tabindex="-1">
      <span class="block truncate">
        
        
      </span>
      <span class="absolute inset-y-0 right-0 flex items-center pr-4 text-indigo-600">
        <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
          <path fill-rule="evenodd"
            d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
            clip-rule="evenodd" />
        </svg>
      </span>
      <span class="ml-2 truncate text-gray-500">
        [email protected]
      </span>
    </li>
  [#&lt;User id: 4, email: &quot;[email protected]&quot;, created_at: &quot;2022-03-18 13:29:04.813660000 +0000&quot;, updated_at: &quot;2022-03-18 13:29:19.397311000 +0000&quot;, first_name: nil, last_name: nil, phone: nil, meta: {}, account_id: 2&gt;]</template></turbo-stream>

this is the user controller

  def search
    keyword = user_params[:keyword] || ""
    @users = User.filter_by_email(keyword)
    respond_to do |format|
      format.turbo_stream do
        render turbo_stream: turbo_stream.update(:owner_search_result, partial: 'users/unit_owner', locals: { users: @users })
      end
    end
  end

the partial is this



  <%= @users.each do |user| %>
    <li
      id=<%= dom_id(user) %>
      class="hover:bg-blue-600 relative select-none py-2 pl-3 pr-9 text-gray-900 cursor-pointer" id="option-0"
      role="option" tabindex="-1">
      <span class="block truncate">
        <%= user.first_name %>
        <%= user.last_name %>
      </span>
      <span class="absolute inset-y-0 right-0 flex items-center pr-4 text-indigo-600">
        <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
          <path fill-rule="evenodd"
            d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
            clip-rule="evenodd" />
        </svg>
      </span>
      <span class="ml-2 truncate text-gray-500">
        <%= user.email %>
      </span>
    </li>
  <% end %>

Thank you so much.


Solution

  • Replace

    <%= @users.each do |user| %>
    

    at the beginning of your partial with

    <% @users.each do |user| %>
    

    because you do not want to render the return value of the each call, which is the iterator itself, into the view. Note the = that needs to be removed.