Rails output polymorphic associations

114 views Asked by At

I want to implement a search functionality in my Rails app by using the pg_search gem. I've set up everything like it says in the documentation. Then I've set up a search controller with a show action:

def show
  @pg_search_documents = PgSearch.multisearch(search_params)
end

The search itself works but I have a really annoying problem in my view. Whatever I do, it always outputs an array of PgSearch::Document objects. Even when I only write this in my view:

<%= @pg_search_documents.each do |document| %>
<% end %>

I get this (I've shortened it):

[#<PgSearch::Document id: 2, content: "…", searchable_id: 28, searchable_type: "Vessel">, #<PgSearch::Document id: 3, content: "…", searchable_id: 27, searchable_type: "Vessel">]

I know that pg_search sets up a polymorphic association which I've never dealt with before — could that be the problem?

Thanks in advance

2

There are 2 answers

0
Todd Agulnick On BEST ANSWER
<%= @pg_search_documents.each do |document| %>
<% end %>

This is a classic error, one I remember being puzzled over when I first started learning Rails. The mistake is using <%= %> with each. The return value of each is the array that you're iterating over (in this case, @pg_search_documents), and by using <%=, you're telling Rails to create a string from that array and insert it into your view. That generally isn't what you want: you want the view to be generated by the code inside the block you're passing to each.

Use <% @pg_search_documents.each do |document| %> instead (omitting the =) and you'll avoid the dump of the array's content.

You may also need to use .searchable as @blelump suggests, but I wanted to answer the other half of your question, as it's a common pitfall.

0
blelump On

To get back to the original source model, searchable call is needed on these search result records, e.g:

<% @pg_search_documents.each do |document| %>
  <%= document.searchable %>
<% end %>

You can also switch back to the source model within your controller, e.g:

@pg_search_documents = PgSearch.multisearch(search_params).collect(&:searchable)

Then, the @pg_search_documents will contain Vessel elements.