Есть способ связать что-то с ассоциативной таблицей ActiveRecord?
Я получаю segments
следующим образом:
@segments = Segment.all
Но, Segment
has_many
products
. Видеть:
models / product.rb:
class Product < ActiveRecord::Base
belongs_to :segment, dependent: :destroy
end
models / segment.rb:
class Segment < ActiveRecord::Base
has_many :products
end
Проблема в том, что я просто хочу получить продукты, статус которых равен 1
. Я могу создать что-то подобное, используя where
в модели Segment
, но как я могу добиться этого для products
?
Что я уже пробовал
Я нашел решение. Взглянуть:
@segments = Segment.find(:all, include: :products, conditions: {products: {status: 1}})
Это сработало, но я думаю, что код может быть лучше.
Почему я думаю, что код может быть лучше
Хорошо, а зачем мне использовать include: :products
, если ассоциация уже существует в моделях? Мы связываем вещи через модель, и я уверен, что этого почти достаточно.
Идеи ?
5 ответов
Несколько советов, которые могут вам помочь.
Для удобства именования я рассматриваю status==1
как active
. Конечно, я понятия не имею, что это значит в вашем конкретном случае.
class Product
ACTIVE=1
def self.active
where(status: ACTIVE)
end
end
Теперь вы пишете что-то вроде:
segment.products.active
И будут возвращены только активные продукты для данного сегмента.
Найденное вами решение, которое будет извлекать все сегменты с (активными) продуктами, можно было бы записать иначе, как показано ниже:
Segment.includes(:products).where(products: {status: 1})
Теперь, почему так подробно: это фактически переводится в запрос sql, поэтому вы должны быть немного более точным в этом отношении.
Если вам нужны только те, кто имеет статус 1
class Segment < ActiveRecord::Base
has_many :products, :conditions => { :status => 1 }
end
В рельсах 3 или
class Segment < ActiveRecord::Base
has_many :products, -> { where status: 1 }
end
В рельсах 4
Очевидно, можно использовать status: true, если это логическое значение
Затем
@segments = Segment.includes(:products)
Segment.joins(:products).where("products.status = 1")
Вы также можете использовать include вместо объединений. Но рельсы преобразуют его в соединение внутри, поскольку вы используете атрибут таблицы продуктов в запросе.
Связь has_many: products позволяет использовать include:: products в вашей области. Поэтому сомневаться в своем решении не стоит. Это правильно, и это то же самое, что и решения, представленные в других ответах, но с другим синтаксисом.
Это должно сработать - и это совместимо с синтаксисом AREL:
@segments = Segment.joins(:products).where(products: {status: 1})
Совсем другое дело решение с include
(или includes
, как было бы Rails 3/4), потому что оно генерирует запрос с INNER JOIN
, а includes
генерирует {{X4 }}. Кроме того, includes
обычно используется для активной загрузки связанных записей, а не для запросов с JOIN
.
joins != includes
, но концептуально то же самое, но с другим синтаксисом.
Похожие вопросы
Новые вопросы
ruby-on-rails
Ruby on Rails - это полнофункциональная платформа веб-приложений с открытым исходным кодом, написанная на Ruby. Он следует популярной модели фреймворка MVC и известен своим подходом «соглашение поверх конфигурации» при разработке приложений.