简体   繁体   中英

"Filtering" results by category in Rails

As a school project I am supposed to create a Task manager app. I'm getting there but one of the things I can't seem to figure out is this: I have 3 models: Task, Category and Tag. A task has one category, but many tags. We are supposed to be able to filter the tasks by category so, that when you select a category, you'll be redirected to /tasks/by-category/category_id. By_category doesn't have a model, just a view in the tasks folder.

My routes:

resources :tasks do
collection do
  get 'net_connection', action: :net_connection
  get 'completed'
  get 'pending'
  get 'by-category', action: :by_category, :as =>  :by_category
  get 'search'
  delete 'destroy_multiple'
end 
  member do
  delete 'delete'
end 

index.html.erb in tasks:

    <div>
<%= simple_form_for :by_category, url: by_category_tasks_path, method: :get  do |f| %>
  <%= f.input :category, collection: Category.all, label_method: :title, value_method: :id,label: "Category", include_blank: true %>
  <%= f.submit "Filter by category" %>
<%end%>
</div>

Tasks controller:

def by_category

    end

How can I submit a category id to the by-category URL?

The Rails way to do this is to create a nested resource:

resources :categories, only: nil do
  resources :tasks, only: :index
end

This creates a /categories/:category_id/tasks route. You can either modify the normal TasksController#index action:

class TasksController
  # GET /tasks
  # GET /categories/1/tasks
  def index
    if params[:category_id]
      @category = Category.includes(:tasks)
                          .find(params[:category_id])
      @tasks = @category.tasks
    else
      @tasks = Task.all
    end
  end 
end

Or create a separate nested controller:

resources :categories, only: nil do
  resources :tasks, only: :index, module: :categories
end
module Categories
  class TasksController
    # GET /categories/1/tasks
    def index
      @category = Category.includes(:tasks)
                          .find(params[:category_id])
      @tasks = @category.tasks
    end 
  end
end

Using a form is overkill as you just creating a simple GET request with a single parameter that is sent in the path. Just create a link for each category:

<%= link_to category.name, [category, :tasks] %>

If you really had to create a form you could do it with:

<%= form_tag tasks_path do |f| %>
   <%= select_tag('category_id', options_from_collection_for_select(Category.all, 'title', 'id')) %>
   <%= submit_tag "Filter by category" %>
<% end %>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM