Как отфильтровать таблицу по атрибутам столбца с помощью ActiveRecords Scope в Rails - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь настроить интерфейс Rails API для проекта книжного магазина, и внешний интерфейс будет реагировать. В бэкэнде пока есть только одна модель - модель Book. Во внешнем интерфейсе я хотел бы отфильтровать книги по их категории. Я хочу настроить фильтрацию на бэкэнде, чтобы при выборе раскрывающегося списка на веб-интерфейсе отображались только книги, соответствующие определенной категории. Пока вот что у меня есть на бэкэнде:

Модель книги

class Book < ApplicationRecord
  validates :title, :category, presence: true

  scope :categorized, -> (category) { where("category LIKE ?",  "#{category}" ) }

end

мой контроллер книги выглядит так:

Контроллер книги

class Api::V1::BooksController < Api::V1::ApiController
   before_action :set_book, only: %i[show update destroy]

   def index
     @books = Book.all
     render json: @books
   end

   def categorized
     @category = params[:book]
     @books = Book.categorized(@category)
     render json: @books
   end

   def show
     render json: @book
   end

  def create
     @book = Book.new(book_params)

     if @book.save
       render json: @book, status: :created
     else
       render json: @book.errors, status: :unprocessable_entity
     end
  end

  def update
    if @book.update(book_params)
       render json: @book
    else
       render json: @book.errors, status: :unprocessable_entity
    end
  end

  def destroy
     @book.destroy
  end

  private

  def set_book
    @book = Book.find(params[:id])
  end

  def book_params
    params.require(:book).permit(:title, :category)
  end

end

Routes.rb

Rails.application.routes.draw do
 namespace :api do
  namespace :v1 do
    resources :books do
      collection do
        get :categorized
      end
    end
  end
end

end

Образец Данные

Вот пример данных, которые я получаю от API, когда запрашиваю все книги в базе данных:

[
{
    "id": 1,
    "title": "I Know Why the Caged Bird Sings",
    "category": "Fable"
},
{
    "id": 2,
    "title": "His Dark Materials",
    "category": "Speech"
},
{
    "id": 3,
    "title": "To Say Nothing of the Dog",
    "category": "Fable"
},
{
    "id": 4,
    "title": "An Acceptable Time",
    "category": "Science fiction"
},
{
    "id": 5,
    "title": "A Scanner Darkly",
    "category": "Suspense/Thriller"
},
{
    "id": 6,
    "title": "The Golden Bowl",
    "category": "Science fiction"
}
]

Меня интересует, что я хочу видеть только "Научная фантастика" «Книги или любую другую категорию я выбираю только с помощью прицелов. Категории не ограничиваются тем, что показано в данных выборки; В действительности они могут увеличиться. Конфигурация, которую я имею выше в модели, не получает то, что мне нужно. Когда я пользуюсь почтальоном, я не получаю никакого результата. Лучшее, что я получаю, это пустой массив.

1 Ответ

0 голосов
/ 23 апреля 2020

scope: категоризированный, -> (category) {где ("category LIKE?", "# {Category}")}

Вы уверены, что эта область нужна только для одно место? Почему бы просто не фильтровать в контроллере? Вторая мысль заключается в использовании Book.where (категория: категория), который будет производить «ГДЕ КАТЕГОРИЯ =?» вместо «ГДЕ категория НРАВИТСЯ» Третье - может быть, вы можете избавиться от категоризованного маршрута и просто использовать индекс с необязательным параметром? Вы также можете добавить пагинацию позже в контроллере индекса - где ... page (page) .per (per) В-четвертых, рекомендуется использовать методы доступа к переменным экземплярам вместо самой переменной:

def set_book @book = Book.find (params [: id]) end

To

def book @book || = Book.find (params [: id ]) end

Также метод find вызывает исключение. Возможно, вы захотите спасти его на уровне класса. Вы также можете использовать book.update! И book.save! другими методами и спасением от них - тогда вам не понадобятся ветки if / else.

...