0

I have a Ruby on Rails schema with two entities: Category which has many Products.

Parent entity (Category)

# Table name: category
#
#  id               :integer          not null, primary key
#  name             :string(50)      not null
#  type_id      :integer


class Admin::Category < ApplicationRecord
has_many :products, class_name: "Admin::ProductCategory", :dependent => :destroy, :inverse_of => :category

Child entity (product_category):

# Table name: product_category
#
#  id                   :integer          not null, primary key
#  product_category_id :integer
#  product_type_id           :integer
#

class Admin::ProductCategory < ApplicationRecord
  belongs_to :Category, inverse_of: :products
  validate :unique_product_type

I am adding validation in product_category to ensure that when a new record is added, there is a unique product for one Category type (in this example 4).

So the unique_product validation method has the following code:

    product_categories = Admin::ProductCategory.where(product_type_id: self.product_type_id)
    
#is there product in the category 4 already?
if product_categories.empty? ? 0 : product_categories.map(&:category).any?{
            |category|  category.type_id == self.category.type_id &&
            category.type_id == 4
 }
    #There is a category type 4. throw error here
end

My question is, can this where condition be simplified and the map avoided?

I tried several example, like the one before, but I cannot get it to work.

product_categories = Admin::ProductCategory.where(product_type_id: self.product_type_id, 
                      category:{type_id:4} )
Shankar
  • 2,625
  • 3
  • 25
  • 49

1 Answers1

1

You can try something as follow:

product_categories = Admin::ProductCategory.joins(:category)
  .where(product_type_id: self.product_type_id)
  .where(categoires: { type_id: self.category.type_id })
  .where(categoires: { type_id: 4 })

And this is a nice explanation of ActiveRecord join with belongs_to relationship https://stackoverflow.com/a/33266583/7338180.