问题
I have a vast list of Lawyers, Categories, and Subcategories.
Hint (so you could have a clue if my associations are okay)
- On Categories Table, I do not want to see a column on Categories Table referencing Subcategories.
- On Subcategories Table, I do not want to see a column on Subcategories Table referencing Categories.
- Not all Categories has Subcategories. i.e. some don't have subcategories as seen in the picture.
- I have 2 separate forms creating category and subcategory.
- I added category_id and subcategory_id as foreign keys to my lawyers table. Such that I can choose from lawyers form upon create, the category or subcategory a lawyer will belong to as soon in the image.
- Also note: A Subcategory could be created at any time, any day, for Categories not having Subcategory, as well as new Subcategories under Categories already having some Subcategories, and lawyers will be placed under them.
- The image is a replica of my index/homepage I am having at the moment, at least before number 6 above takes effect any time any day, and I hope to use loop to make this view happen.
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.
回答1:
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.
来源:https://stackoverflow.com/questions/39281493/association-between-category-subcategory-and-lawyer