Search code examples
ruby-on-railsactiverecorddrop-down-menufilternested-resources

Rails - Sorting deep nested resources on index page from dropdown by primary model


So I have three models: Topic, Post and Paragraph. Each Topic has many Posts and each Post has many Paragraphs. What I need to achieve is to sort the Paragraphs by Topic on paragraphs/index.html.erb.

I of course have the dropdown menu including all the topics:

<form>    
  <select>
    <% @topics.sort { |a,b| a.name <=> b.name }.each do |topic| %>
      <option><%= topic.name %></option>
    <% end %>
  </select>
 <input type="submit">
</form>

I followed the advice on: Filter results on index page from dropdown, but I couldn't manage to come up with a way to connect Topic params first to Post and then to Paragraph. I simply have no idea how to go with it, and there doesn't seem to be many examples out there, so any ideas are hugely appreciated.


Solution

  • Before start, check if you specified accepts_nested_parameters_for ... in post.rb and topic.rb

    OK, now we need to adjust routing to make the magic happens. Just add to routes.rb:

    patch 'paragraphs' => 'paragraphs#index'
    #we'll use PATCH for telling index which topic is active
    

    Paragraphs#index remains the same:

    def index
      @topics = Topic.all
    end
    

    The rest we'll do in view. So, index.html.erb:

    <h1>Listing paragraphs sorted by Topic</h1>
    
    <% names_options = options_from_collection_for_select(@topics, :id, :name, selected: params[:topic_id]) %>
    
    <%= form_tag({action: "index"}, method: "patch") do %>
      <%= select_tag :topic_id, names_options, 
                    {prompt: 'Pick a topic', include_blank: false} %>
      <%= submit_tag "Choose" %>
    <% end %>
    
    <% @topics = @topics.where(:id => params[:topic_id]).includes(:posts => :paragraphs) %>
    
    <% @topics.each do |topic| %>
      <option><%= topic.name %></option>
      <h2><%= topic.name %></h2>
      <% topic.posts.each do |post| %>
        <h3><%= post.content %></h3>
        <% post.paragraphs.each do |paragraph| %>
        <%= paragraph.content %><br>
        <% end %>
      <% end %>
    <% end %>
    

    Viola!