Reputation: 45
I am currently developing a small project, it is a classifieds application.
For this app I have the following requirement: we will have a set of categories, each of them will store different information, e.g: the classifieds for vehicle will need to have information related to engine, year of fabrication, mileage, description and real state related ads will obviously not going to have this info but instead will need to store type of property, price, year, number of rooms, and so on for every other category.
So the question is: what would be the best approach to tackle this problem so that I can:
1) Fetch ads from all categories when doing a search and display them in a single results page.
2) Save the data corresponding to each category but avoid having too many empty columns in my database models
What I have thought about this is, to have a single Product model, with the most general attributes abstracted in it, this model will belong_to a Category model, that will determine the next association, probably a belongs_to category_attributes. Then this will require me to have an attributes table for each category and depending on the category selected for the product I will have something like the following:
Product with category "vehicles" has_one vehicles_attributes.
I would like to know what is the 'Rails way' of handling this situation
Thanks.
Upvotes: 0
Views: 354
Reputation: 10693
Your approach is ok and will work fine if the category set is quite static. It will require changes whenever you would add a new category and/or attributes.
One idea that worked for me once when I needed more flexibility was:
# Migration
create_table :products do |t|
t.integer :category_id
t.string :name
t.string :description
t.[...] # maybe other common fields here
t.string :spec_attrs, limit: 1000
t.timestamps
end
# Model
class Product
belongs_to :category
serialize :spec_attrs, Hash
end
This setup allows you to create different products like:
Product.create(category: Category.find_by(:name, "Vehicles"),
name: "M1 Abrams",
description: "..."
spec_attrs: { year: 1975,
transmission: "manual"
max_speed: 72 })
Product.create(category: Category.find_by(:name, "Estates"),
name: "Taj Mahal",
description: "..."
spec_attrs: { year: 1653,
rooms: 268,
country: "India",
city: "Agra" })
An obvious drawback is that is requires more effort to validate attribute existence, types and values (must do that programatically), watch out for length of spec_attrs if you have more descriptive attributes, etc. Think what you would need in the future and decide.
Upvotes: 1