Search code examples
ruby-on-railsslim-lang

How to get the checked boxes with link_to into params?


I have a Rails 5.2.1 app with Movies and Categories. They are connected to one another through a has_and_belongs_to_many relation with a join table.

Trying to do the following: on the index page for Movies, I want to filter the collection of movies that is shown by checking Category check boxes. I can properly show check boxes for the Categories, but I'm having a hard time getting the information about what check boxes are checked into the params.

/ rails_app/app/views/movies/index.html.slim
h1 Listing movies

= collection_check_boxes(@movies, :category_ids, Category.all, :id, :name) do |box|
  = box.check_box
  = box.label

= link_to 'Filter movies on category', params.permit!.merge(filter: :category_ids)

table
  / table with movies that will be filtered

These :category_ids seem to be wrong. Is it possible to somehow get at the check box results in this way (for further filtering with query string parameters)? Am I missing something, e.g. in my controller?

# rails_app/app/controllers/movies_controller.rb
class MoviesController < ApplicationController
  def index
    @movies = Movie.all
  end

...

  def movie_params
    params.require(:movie).permit(:name, :rating, category_ids: [])
  end
end

The above is an example app, generated with some scaffolds and a few edits:

rails generate scaffold category name:string
rails generate scaffold movie name:string rating:integer
rails generate migration CreateJoinTableMoviesCategories movie category
bin/rails db:migrate RAILS_ENV=development
-> add has_and_belongs_to_many :movies to Category class
-> add has_and_belongs_to_many :categories to Movie class
-> add category_ids: [] to movie_params in Movie class


Solution

  • try this and see if it works for you.

    View:

        / rails_app/app/views/movies/index.html.slim
    
        = form_for :movie do |f|
         = f.collection_check_boxes(:category_ids, Category.all, :id, :name) do |box|
          = box.check_box
          = box.label
         = f.submit
    
        / table with movies that will be filtered
    

    Controller:

    # rails_app/app/controllers/movies_controller.rb
    class MoviesController < ApplicationController
      def index
        @movies = if params[:movie]
                    Movie.joins(:categories).where(categories: { id: params[:movie][:category_ids] })               
                  else
                    Movie.all
                  end
      end
      ... 
    

    Essentially, wrapping the checkboxes inside a form, then tweak index action when filter params exists.

    Note: I'm not familiar with slim syntax, so tweak it if you get syntax error :).