I have a vast list of Lawyers, Categories, and Subcategories.
Hint (so you could have a clue if my associations are okay)
Pictorial understanding of what I am trying to do:
Here are my relationships between 3 models
class Lawyer < ActiveRecord::Base
belongs_to :category
belongs_to :subcategory
end
class Category < ActiveRecord::Base
has_many :lawyers
end
class Subcategory < ActiveRecord::Base
#belongs_to :category #Do I want "category_id" in Subcategories Table?
has_many :lawyers
end
Question
Is my association on those 3 models okay for the Hint I gave? This is pretty confusing.
You don't need a Subcategory
model/table, specially if they have the same columns. Your categories
table should have a parent_id
column. A category is a subcategory when it has a parent_id
value pointing to another category record. Categories with a NULL
parent_id
are the top level categories.
Example
class Lawyer < ActiveRecord::Base
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :lawyers
# This is called a self referential relation. This is where records in a
# table may point to other records in the same table.
has_many :sub_categories, class_name: "Category", foreign_key: :parent_id
# This is a scope to load the top level categories and eager-load their
# lawyers, subcategories, and the subcategories' lawyers too.
scope :top_level, -> { where(parent_id: nil).include :lawyers, sub_categories: :lawyers }
end
Note: you should create a migration to add the parent_id
column to the categories table. And you can drop the subcategories table.
Now create some of your categories (I'm assuming there's a name
column):
cat = Category.create name: "Corporate and Commercial Law"
subcat = Category.new name: "Corporate Tax", parent_id: cat.id
subcat.lawyers << Lawyer.find_by_name("Sabina Mexis")
subcat.save
Example table of contents:
<% Category.top_level.each do |cat| %>
<%= cat.name %>
<% cat.sub_categories.each do |subcat| %>
<%= subcat.name %>
<%= subcat.lawyers.each do |laywer| %>
<%= lawyer.name %>
<% end %>
<% end %>
<% end %>
The above is a simplified example. Hope that helps.
Update
To enhance your form to allow you to create a subcategory and assign its parent category, use a select menu filled with top_level
category IDs:
<%= form_for Category.new do |f| %>
<%= f.text_field :name %>
<%= f.select :parent_id, options_from_collection_for_select(Category.top_level, :id, :name) %>
<%= f.submit %>
<% end %>
Check out the docs for options_from_collection_for_select if it's unfamiliar. What it does is build a select menu with the category:id
as values and their :name
as the text in the menu. Make sure you add :parent_id
to your strong parameters to allow mass assignment via params[:category]
.
The laywer
error was just a typo in my example code, it's fixed now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With