Фильтрация отношения в Rails

У меня есть это отношение в моем Product модель:

has_many :features, :class_name => 'ProductFeature', :source => :product_feature, :include => :feature

Так что я могу сделать Product.features

который отлично работает Но я хочу иметь возможность фильтровать это по полям в feature стол, когда и при необходимости. Например, в псевдокоде:

find all product features where feature is comparable

compare это поле bool на feature,

Я пытался в течение 2 часов твердо и не могу понять это (без написания нового запроса полностью). Я не могу понять, как получить доступ к feature поля таблицы из Product.features отношение, как кажется, может фильтровать только product_features поля.

Это то, что я придумал до сих пор:

def features_compare
  features.feature.where(:compare => true)
end

Но это просто говорит feature это недопустимый метод, который я понимаю.

редактировать

Я обновил свою модель, чтобы отношения стали понятнее:

product.rb:

class Product < ActiveRecord::Base
  belongs_to :company
  belongs_to :insurance_type

  has_many :product_features
  has_many :reviews

  attr_accessible :description, :name, :company
end

product_feature.rb:

class ProductFeature < ActiveRecord::Base
  belongs_to :product
  belongs_to :feature

  delegate :name, :to => :feature

  attr_accessible :value
end

feature.rb

class Feature < ActiveRecord::Base
  attr_accessible :name, :compare
end

Я хочу иметь возможность запросить product_features которые принадлежат product а также feature где Feature.compare является true, Что-то вроде этого:

product.rb

def features_compare
  product_features.where(:compare => true)
end

Это выдает ошибку, потому что compare в в Feature модель, а не ProductFeature, Я попробовал следующее в product_feature.rb:

delegate :compare, :to => :feature

но я не помог

Я добавлю награду через несколько часов, поэтому, пожалуйста, помогите мне!

3 ответа

Решение

find all product features where feature is comparable просто

ProductFeature.joins(:feature).where(:feature => {:compare => true})

Вы можете сделать это немного более пригодным для повторного использования, введя область видимости:

#in product_feature.rb
scope :with_feature_like, lambda do |filter|
   joins(:feature).where(:feature => filter)
end

#elsewhere
ProductFeature.with_feature_like(:compare => true)

#all the product features of a certain product with at comparable features
some_product.product_features.with_feature_like(:compare => true)

Наконец, если вы хотите, чтобы все продукты с характеристиками продуктов были сопоставимы, вам нужно что-то вроде:

Product.joins(:product_features => :feature).where(:feature => {:compare => true})

что, конечно, вы также можете превратить в прицел на Product,

Это похоже на has_many: сквозные отношения. Попробуйте изменить это:

has_many :features, :class_name => 'ProductFeature', :source => :product_feature, :include => :feature

к этому:

has_many :product_features
has_many :features, :through => :product_features

Пока ваша модель ProductFeature имеет это:

belongs_to :product
belongs_to :feature

И у вас есть соответствующие столбцы в product_features (product_id, feature_id), и вы сможете получить доступ к функциям этого продукта и всем атрибутам в Product и ProductFeature.

Посмотреть здесь:

http://guides.rubyonrails.org/association_basics.html

РЕДАКТИРОВАТЬ: Вот как фильтровать по полям объектов.

Product.joins(:features).where(:features => {:name => "Size"})

@product.each |p| { p.features.where(:comparable => true) } Вероятно, ваш лучший выбор здесь, но я открыт для просвещения.

Другие вопросы по тегам