Работаю пятый месяц, это первая работа. Rails 8.1, Turbo Frames, база SQLite. Каталог с фильтрами, и экшен index разросся:
def index
@products = Product.all
if params[:category].present?
@products = @products.where(category_id: params[:category])
end
if params[:min_price].present?
@products = @products.where("price >= ?", params[:min_price])
end
if params[:max_price].present?
@products = @products.where("price <= ?", params[:max_price])
end
if params[:in_stock] == "1"
@products = @products.where("stock > 0")
end
# и ещё четыре таких же
@products = @products.order(params[:sort] || "created_at DESC")
end
Ревьюер написал «вынеси фильтры», а куда именно, не сказал. В проекте есть и scopes, и класс ProductSearch, которым никто не пользуется. Как правильно?
Ревьюер, скорее всего, хотел scopes. Это первый шаг, и для многих проектов он же последний. Каждый scope сам решает, что делать с пустым значением, а контроллер превращается в одну цепочку:
class Product < ApplicationRecord
scope :in_category, ->(id) { where(category_id: id) if id.present? }
scope :price_from, ->(v) { where(price: v.to_d..) if v.present? }
scope :price_to, ->(v) { where(price: ..v.to_d) if v.present? }
scope :in_stock, ->(flag) { where(stock: 1..) if flag == "1" }
end
@products = Product.in_category(params[:category])
.price_from(params[:min_price])
.price_to(params[:max_price])
.in_stock(params[:in_stock])
Если scope возвращает nil, Rails подставляет all, поэтому условие внутри работает как надо.
А сортировку из параметров в order напрямую не пропускай, даже если Rails сейчас и отсекает откровенный SQL. Белый список:
SORTS = {
"new" => { created_at: :desc },
"cheap" => { price: :asc },
"pricey" => { price: :desc }
}.freeze
@products = @products.order(SORTS.fetch(params[:sort], SORTS["new"]))
ProductSearch пригодится, когда фильтры начнут зависеть друг от друга или появится полнотекстовый поиск. Пока хватает scopes, не торопись.
Сделал scopes как у Егор64 и белый список сортировки, ProductSearch удалил с одобрения ревьюера. Экшен стал на шесть строк. Спросил ревьюера прямо, что он имел в виду: именно scopes, а сортировку он и сам не заметил, так что меня ещё и похвалили) Тест на неизвестную сортировку тоже добавил.