#ruby-on-rails #activerecord #where-clause
#ruby-on-rails #activerecord #where-предложение
Вопрос:
проекты == has_many ==>
<== has_many ==
этапы проекта_stages
Я пытаюсь выбрать те проекты, в которых stage.name = ‘завершено’, поэтому я подумал, что сработает одно из следующих действий:
Project.joins(:stages).where(stages: { name: 'completed' })
Project.where(stage: Stage.find_by(name: 'completed'))
Нет кубиков.
Модели:
class Project < ApplicationRecord
...
has_many :project_stages
has_many :stages, through: :project_stages
...
end
class ProjectStage < ApplicationRecord
belongs_to :project
belongs_to :stage
end
class Stage < ApplicationRecord
has_many :project_stages
end
Комментарии:
1.
Project.joins(project_stages: :stages).where(stages: { name: 'completed' }).distinct
должно работать для вас, хотя в зависимости от того, как вы собираетесь использовать эти данныеProject.includes(:project_stages).where(project_stages: {stage_id: Stages.find_by_name('complete').id})
, может быть более эффективным2. Выдает мне эту ошибку:
ActiveRecord::ConfigurationError: Can't join 'ProjectStage' to association named 'stages'; perhaps you misspelled it?
(одинаково для обоих)3. Какой SQL-запрос генерируется из той первой строки, которую вы пробовали?
4. @Daniel причина, по которой вы получили сообщение об ошибке, опубликованное @engineersmnky, заключается в том, что существует небольшая ошибка в том, что этапы множественны в
joins
методе, когда этого не должно быть. Это будет работать:Project.joins(project_stages: :stage).where(stages: {name: 'completed'})
5. Прибил его! Работает безупречно. У вас случайно нет ресурса по этому вопросу, который вы могли бы порекомендовать?
Ответ №1:
Я думаю scopes
, они хорошо подходят для этого:
scope :search_by_stages, ->(param){
joins(:stages).where(Stage.arel_table[:name].lower.eq(param.downcase))
}
Вы можете добавить scope
указанное выше в свою Project
модель, где param
указано имя (этот поиск не чувствителен к регистру, вы можете удалить lower
и downcase
, если хотите, чтобы он учитывал регистр).
Вы можете использовать его следующим образом (на случай, если вы не знакомы с областями): Project.search_by_stages('name')
Надеюсь, что вышесказанное поможет! 👍