I have a model movies in my Ruby on Rails application and I want to have a few easy links that show different subsets of it - for example, movies not seen, movies that do not have a production year entered, movies rated as "great" etc.
I have created scopes for all of these conditions in my movie model, e. g.
scope :no_year, -> { where(release_year: [0, nil, ""]) }
But then I want to have a list of these subsets - as said, a list of links where user can click and will get the results in a default view (the movie index view actually). So I have a list of links such as the below, which required me to add routes as well as methods for all of these scopes that look pretty much the same.
<%= link_to 'Movies without a Year', noyear_movies_path %>
(<%= Movie.no_year.count %>)
routes.rb:
resources :movies do
get :noyear, on: :collection
end
movies_controller.rb:
def noyear
@q = Movie.no_year.ransack(params[:q]) # using Ransack for a sidebar that is displayed
@pagy, @movies = pagy(@q.result(distinct: true)) # using pagy to split up results
render 'index'
end
EDIT: added index and sidebar method code.
My index method looks like this:
def index
@pagy, @movies = pagy(@q.result(distinct: true))
end
... and the variable q itself is set application wide, as it is defined in a sidebar that contains a little search field that is always displayed:
def sidebar_q_movie
@q = Movie.ransack(params[:q])
end
I am sure this can be achieved way nicer. But since I am still pretty new to Ruby, I don't know that. Any hints appreciated!
CodePudding user response:
Rather than having separate routes for each movie filter, you could specify the filter with a query param to Movies#index
<%= link_to 'Movies without a Year', movies_path(filter: 'no_year') %>
and in the controller:
def index
@movies = Movies.send(params[:filter])
end
Of course, you would want to validate the filter param first by checking against a list of permitted strings.