How to implement in rails a category that can be child of another category (self-referential has_one) ?
Thanks
How to implement in rails a category that can be child of another category (self-referential has_one) ?
Thanks
Add a column category_id
to the categories table and then tell the Category model, that it belongs to itself:
class Category < ActiveRecord::Base
belongs_to :category
end
For clarity's sake, you might want to name the association child
instead of category
, so you can name the column child_id
and then do:
class Category < ActiveRecord::Base
belongs_to :child, :class_name => :category
end
First, I believe you want a has_many relationship, not a has_one. I can't imagine a situation where you would want categories to have at most one child category. The previous answer also only gets you one direction - categories know about their parents, but not about their children.
The full solution is simple enough. The categories table should have a category_id column, and the model should look like this:
class Category < ActiveRecord::Base
belongs_to :category
has_many :categories
end
If you want to go a step further and call them parents and children, you can:
class Category < ActiveRecord::Base
belongs_to :parent, :class_name => 'Category', :foreign_key => 'category_id'
has_many :children, :class_name => 'Category', :foreign_key => 'category_id'
end
Good luck with your app!
The simple approach is to use a foreign key of category_id
as others have already pointed out. However, if you're talking about nesting lots of categories this can be pretty inefficient. (Note: Posting more of your requirements would be helpful.)
I really, really like the ancestry gem. Here is a relevant snip from the docs (emphasis mine).
As can be seen in the previous section, Ancestry stores a path from the root to the parent for every node. This is a variation on the materialised path database pattern. It allows Ancestry to fetch any relation (siblings, descendants, etc.) in a single sql query without the complicated algorithms and incomprehensibility associated with left and right values. Additionally, any inserts, deletes and updates only affect nodes within the affected node’s own subtree.
And, here's a bonus freebie, just because it's not immediately obvious. If you need to treat siblings as a list with positions, you can scope them as follows.
acts_as_list :scope => 'ancestry #{(ancestry.blank? ? "IS NULL" : "=\'" + ancestry + "\'")}'