Reputation: 11
Here is the situation: a store has many products, and can join multiple alliances. But the store owner may not want to display certain products in some alliances. For example, a store selling computers and mobile phones might want to display only phones in a "Phone Marts".
By default, all products in the store will be displayed in all alliances one shop joins. So I think building a product-alliance blacklist (I know it's a bad name...any ideas?) might be a convenient way.
The question is: how to create a "has_many" to reflect such relations like the behaviours of function shown_alliances
and shown_products
?
I need this because Car.includes(:shop, :alliances)
is needed elsewhere, using functions make that impossible.
Product:
class Product < ActiveRecord::Base
belongs_to :store
has_many :alliances, -> { uniq }, through: :store
has_many :blacklists
def shown_alliances
alliances.where.not(id: blacklists.pluck(:alliance_id))
end
end
Store:
class Store < ActiveRecord::Base
has_many :products
has_many :alliance_store_relationships
has_many :alliances, through: :alliance_store_relationships
has_many :allied_products, -> { uniq }, through: :alliances, source: :products
end
Alliance:
class Alliance < ActiveRecord::Base
has_many :alliance_store_relationships
has_many :store, through: :alliance_store_relationships
has_many :products, -> { uniq }, through: :companies
has_many :blacklists
def shown_produtcts
@produtcts ||= produtcts.where.not(id: blacklists.pluck(:produtct_id))
end
end
Blacklist:
class Blacklist < ActiveRecord::Base
belongs_to :produtct
belongs_to :alliance
validates :produtct_id, presence: true,
uniqueness: { scope: :alliance_id }
end
Upvotes: 1
Views: 102
Reputation: 6603
class Product < ActiveRecord::Base
# ...
has_many :shown_alliances, ->(product) { where.not(id: product.blacklists.pluck(:alliance_id) }, class_name: 'Alliance', through: :store, source: :alliances
# ...
end
class Alliance < ActiveRecord::Base
# ...
has_many :shown_products, ->(alliance) { where.not(id: alliance.blacklists.pluck(:product_id) }, class_name: 'Product', through: :companies, source: :products
# ...
end
You can specify a condition for associations. See docs here
Upvotes: 1