I have nested routes of categories/subcategories/products and my controller and view files are setup accordingly, but I now have some products that don't have subcategories. How, if possible, can I have some products part of a category, while others are part of a sub-category? I've seen many other posts on this, but none seem to address exactly what I'm looking to do.
current nested routes
resources :categories do
resources :subcategories do
resources :products
end
end
additional needed nested routes
resources :categories do
resources :products
end
My current Products controller Create method
def create
@category = Category.friendly.find(params[:category_id])
@subcategory = Subcategory.friendly.find(params[:subcategory_id])
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to category_subcategory_product_path(@category, @subcategory, @product), notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: category_subcategory_product_path(@category, @subcategory, @product) }
else
...
end
end
end
models
class Category < ApplicationRecord
has_many :subcategories
has_many :products, through: :subcategories
end
class Subcategory < ApplicationRecord
has_many :products
belongs_to :category
end
class Product < ApplicationRecord
belongs_to :subcategory
end
What I would do here is remove the Subcategory model and let Categories belong to themselves. This would let you create a nesting hierarchy of categories (which would allow you to get even more granular, if you wanted to).
class Category
has_many :categories
belongs_to :category
has_many :products
end
class Product
belongs_to :category
end
Any "top level" categories would have a category_id
of nil
, and any subcategories would belong_to
an existing one.
top_level = Category.create(slug: "top_level", category_id: nil)
subcategory = Category.create(slug: "subcategory_1", category_id: top_level.id)
Product.create(category: top_level)
Product.create(category: subcategory)
In your routes, you can make something like this:
get "/:category/products", to: "products#index"
get "/:category/:subcategory/products", to: "products#index"