Таблица соединений Rails: как собирать данные по параметру

#ruby-on-rails #postgresql

Вопрос:

У меня есть два объекта: Project amp; Specialty .

Они соединены с таблицей соединений: ProjectSpecialty

Модели следующие:

 class Project < ApplicationRecord
  has_many :project_specialty
  has_many :specialties, :through => :project_specialty
end
 
 class Specialty < ApplicationRecord
  has_many :project_specialty
  has_many :projects, :through => :project_specialty
end
 
 class ProjectSpecialty < ApplicationRecord
  belongs_to :project
  belongs_to :specialty
end
 

Я пытаюсь вызвать набор проектов, которые фильтруются по Specialty .

Контроллер:

 def index
    @projects = Project.all
    if params[:project_specialty].present?
      @specialty = Specialty.find(params[:project_specialty])
      @projects = Project.where(specialties: @specialty.id)
    end
  end
 

Это возвращает только одну запись, когда я запускаю это действие с индексом, хотя существует несколько проектов с определенной специализацией. Что я делаю не так?

Ответ №1:

Самый простой способ определить вложенный ресурс-это:

 resources :specialities do
  resources :projects, only: [:index]
end
 

Это дает вам маршрут /specialities/:speciality_id/projects .

Вы можете настроить свой контроллер следующим образом:

 class ProjectsController < ApplicationController
  # GET /projects
  # GET /specialities/1/projects
  def index
    if params[:speciality_id].present?
      @specialty = Specialty.find(params[:specialty_id])
      @projects = @specialty.projects
    else
      @projects = Project.all
    end
  end
end
 

Но вы также можете использовать отдельный контроллер для вложенного контекста:

 resources :specialities do
  resources :projects, only: [:index], 
                       module: :specialities 
end
 
 module Specialities 
  class ProjectsController < ApplicationController
    # GET /specialities/1/projects
    def index
      @specialty = Specialty.find(params[:specialty_id])
      @projects  = @specialty.projects
    end
  end
end
 

Преимущество заключается в том, что этот контроллер выполняет только одну работу.