Reputation: 359
I want to combine similar methods and views into one, but still keep the url name, like the following:
Home/recommends/categories/shopping
Home/recommends/categories/nightview
Home/recommends/categories/food
Home/recommends/categories/area
I don't want to use params like "?something=xyz"
in url.
In routes.rb
:
resources :recommends, only: :index do
collection do
resources :categories, only: :show, controller: 'recommends' do
collection do
get :food
get :area
get :shopping
get :nightview
end
end
end
end
In controllers:
def food
set_paginator
@recommends = UserRecommend.where(category: "food").order('created_at desc').offset(@offset).limit(@limit).all
@number_of_recommends = UserRecommend.where(category: "food").count
end
def area
set_paginator
@recommends = UserRecommend.where(category: "area").order('created_at desc').offset(@offset).limit(@limit).all
@number_of_recommends = UserRecommend.where(category: "area").count
end
...
In views I have:
food.html.slim
area.html.slim
shopping.slim
nightview.slim
Which are using the same code, just different names in h1
:
h1
| Shopping ( or Area or Food... )
= " (#{@number_of_recommends})"
= render partial: "layouts/paginator",
locals: { total_items: @number_of_recommends, per_page: @limit, current_page: @page }
= render partial: "table", locals: { recommends: @recommends }
Can anyone help me refactor this code?
Upvotes: 1
Views: 36
Reputation: 239240
You can (and should) have a single route, a single action, and a single view. The key is to make the variable portion of your URL into an actual variable. You do this using dynamic segments.
First, a single route. There is no need to use resources
if you're not actually generating multiple RESTful actions:
get "/recommends/categories/:category" => "categories#show"
You can add criteria on what is allowed for the :category
segment:
get "/recommends/categories/:category" => "categories#show", category: /food|area|shopping|nightview/
Next, a single action:
class CategoriesController < ApplicationController
before_action :set_paginator
def show
# params[:category] is "food"/"area"/etc
categories = UserRecommend.where(category: params[:category]).order('created_at desc')
@recommends = categories.offset(@offset).limit(@limit)
@number_of_recommends = categories.count
end
end
Finally, a single view:
# app/views/categories/show.slim
h1
= params[:category].capitalize
= " (#{@number_of_recommends})"
= render partial: "layouts/paginator",
locals: { total_items: @number_of_recommends, per_page: @limit, current_page: @page }
= render partial: "table", locals: { recommends: @recommends }
I would consider it better to use localization to turn the params[:category]
into a title, which would give you more control, rather than relying on simple capitalization of the URL segment:
# app/views/categories/show.slim
h1
= t params[:category]
And:
# config/locals/en.yml
en:
categories:
show:
food: 'Food'
area: 'Area'
nightview: 'Night View'
Upvotes: 3