Reputation: 547
So lets say that I have a Product and Category model. There is a one to many relationship between them ( category has many products, product belongs to category ). I create a collection of categories based on certain criterias using a named scope. Lets call this collection A. Then I would like to create a collection of products which belongs to either category in collection A.
How can I do this?
My guess would be to use the ids of collection A ( A.ids ) and use map or lambda to check if the category_id of a product is included in the array of ids I built from collection A. I am not sure how to do this exactly, and if is the most efficient way to achieve the end result.
Upvotes: 0
Views: 2621
Reputation: 472
The simplest way is actually to take ids and use them to select products.
category_ids = Category.some_scope.pluck(:id)
products_collection = Product.where(category_id: category_ids)
Unless it is not always - that you need to select products from many categories - then maybe you should do that way with collection model, that suggested @dimakura
Upvotes: 1
Reputation: 9485
Join on association, filter by accociated objects (joins
/merge
combo)
Product.joins(:category).merge(Category.whatever_scope(you, have))
Subquery on association
Product.where(category: Category.whatever_scope(you, have))
Upvotes: 1
Reputation: 7655
I would suggest to arrange your models like this:
class Category
has_many :products
has_many :category_collections
end
class CategotyCollection
belongs_to :category
belongs_to :collection
end
class Collection
has_many :category_collections
has_many :categories, through: :category_collections
has_many :products, through: :categories
end
In the end of the day, you can select products in given collection as simple:
collection = CategoryCollection.first
collection.categories # => all categories in this collection
collection.products # => all products in this collection
Upvotes: 1
Reputation: 76774
I'd be tempted to employ a has_many :through
relationship, although it's really just a "join" model that's required:
I originally thought of a has_and_belongs_to_many
relationship, but that wouldn't be able to discern the different categories.
--
#app/models/collection.rb
class Collection < ActiveRecord::Base
#columns id | name | category_id | product_id
belongs_to :category
belongs_to :product
end
Having a Collection
model like this will give you the ability to call the following:
@collection = Collection.find_by name: "New products"
@collection.categories #-> all categories
@collection.products #-> all products
This will give you the ability to relate the products
and categories
as follows:
#app/models/product.rb
class Product < ActiveRecord::Base
has_many :categories
has_many :collections
has_many :collection_categories, through: :collections
end
#app/models/category.rb
class Category < ActiveRecord::Base
has_many :products
has_many :collections
has_many :collection_products, through: :collections
end
Changing your Product
and Category
models is optional. It would be for if you wanted the following:
@category = Category.find "1"
@category.collection_products # -> pulled from collections (IE not the `has_many/belongs_to` relationship you have now.
@product = Product.find "2"
@product.collection_categories # -> all categories through the collections table
Upvotes: 1
Reputation: 3180
When you say that you "would like to create a collection of products which belongs to either category in collection A" that automatically makes it a many to many relationship. In reality one product can belong to many categories, and a category can have many products. Therefore, I would create a join table to solve your issue.
Upvotes: 0