Найти запись на основе связанных атрибутов

Я пытаюсь найти запись на основе двух связанных атрибутов. Запись должна быть выбрана, если ее ассоциация содержит эти две записи.

До сих пор я пытался следовать - что мне показалось очень плохой практикой, и я хочу избежать ее использования.

@size = Spree::OptionValue.find(params[:size])
@color = Spree::OptionValue.find(params[:color])

vari = Spree::Variant.all
vari.each do |va|
  if va.option_values.include?(@size && @color)
    @variant = va
  end
end

До сих пор я также пытался

@variant = Spree::Variant.all(:include => :option_values, :conditions => ['option_value.id = ?', params[:color])

Кажется, это путь, но я не могу понять, как правильно получить результат. Ошибка возврата, которую я продолжаю получать, следующая:

ActiveRecord::StatementInvalid: PG::Error: ERROR: отсутствует запись предложения FROM для таблицы "option_values" LINE 1: ..._option_values_variants"."option_value_id" WHERE (option_val...

РЕДАКТИРОВАТЬ:

У меня это заработало благодаря большой помощи, предоставленной в принятом ответе:

Spree::Variant.joins(:option_values).where("spree_option_values.id in (?)", [size, color])

person Martin Lang    schedule 06.11.2012    source источник
comment
попробуй сделать option_values.id, как ассоциацию.   -  person numbers1311407    schedule 07.11.2012
comment
Это не решает проблему, к сожалению.   -  person Martin Lang    schedule 07.11.2012
comment
Действительно нужно увидеть ваши модели и ассоциации, чтобы понять это.   -  person meagar    schedule 07.11.2012
comment
Я только что посмотрел источник. Это привычка. github.com/spree/spree/blob/master/ ядро/БД/мигрировать/   -  person numbers1311407    schedule 07.11.2012
comment
Спасибо, да - это HABTM.   -  person Martin Lang    schedule 07.11.2012


Ответы (1)


Во-первых, ваш код, вероятно, сломан. Я сомневаюсь, что .include?(@size && @color) делает то, что вы думаете; вы фактически только проверяете, включает ли option_values @color. Это эквивалентно выполнению (true && @color). Если вы хотите включить оба значения, вам нужно .include?(@size) && .include?(@color).

Таким образом, ваш код, вероятно, должен выглядеть так:

vari = Spree::Variant.all
vari.each do |va|
  if va.option_values.include?(@size) && va.option_values.include?(@color)
    @variant = va
  end
end

Далее вы можете сделать свой код более похожим на Ruby:

@variant = Spree::Variant.all.select do |v|
  v.option_values.include?(@size) && v.option_values.include?(@color)
end

Но гораздо лучше оценить условие на уровне базы данных, чем загружать всю таблицу в ваше приложение. Кажется, вы ищете все записи, в которых связанные OptionValue включают две выбранные вами @size и @color.

Запрос, который вы ищете, вероятно, выглядит примерно так:

Spree::Variant.joins(:option_values).where("option_values.id in (?)", [@size, @color])
person meagar    schedule 06.11.2012
comment
Кажется, это путь для меня. Если я пытаюсь подтвердить функциональность в консоли, я продолжаю получать следующий ответ › ActiveRecord::Relation:0x3fd43f225ef4 - person Martin Lang; 07.11.2012
comment
Потому что Rails дает вам отношение, готовое к дополнительной цепочке scope/where/join. Вам нужно использовать его для Rails, чтобы превратить его в список записей; использование .all поможет. - person meagar; 07.11.2012
comment
Ах. Кажется, я понимаю. К сожалению, это приводит к NoMethodError: undefined method `where' for #‹Array:0x007fa88126e158›. Я не знаю, почему это обрабатывается как массив? - person Martin Lang; 07.11.2012
comment
Нет, извините, вам нужно добавить .all в самый конец оператора, перед .where. - person meagar; 07.11.2012
comment
Это то, что я делал. › Spree::Variant.joins(:spree_option_values).all.where(option_values.id в ?, [@size, @color]) - person Martin Lang; 07.11.2012
comment
Аргх, извините, я опечатался. Вам нужно добавить его в конец инструкции. Я хотел сказать после где. - person meagar; 07.11.2012
comment
Да, это, кажется, более или менее делает то, что я должен. Но он возвращается с замечательным утверждением: ActiveRecord::StatementInvalid: PG::Error: ERROR: синтаксическая ошибка в или около 553775723 LINE 1: ...nts.option_value_id WHERE (option_values.id в 553775723,...) Я извините, я продолжаю возвращаться с этой проблемой, но у меня действительно кончился бензин. - person Martin Lang; 07.11.2012
comment
Проблема решена - нужно обернуть ? в (). Я отредактирую рабочий запрос в топе. - person Martin Lang; 07.11.2012