Фильтрация отношения в 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) }
Вероятно, ваш лучший выбор здесь, но я открыт для просвещения.