类别,子类别和律师之间的关联

我有很多律师,类别和子类别。

提示 (如果我的协会合适 ,你可以有一个线索)

  1. 在类别表上,我不希望在类别表上看到引用子类别的列。
  2. 在子类别表上,我不希望在Subcategories表上看到引用类别的列。
  3. 并非所有类别都有子类别。 即一些没有图中所示的子类别。
  4. 我有2个单独的表单创建类别和子类别。
  5. 我将category_id和subcategory_id作为外键添加到我的律师表中。 这样我就可以在创建时选择律师forms,律师将在图像中尽快选择类别或子类别。
  6. 另请注意:对于没有子类别的类别,可以在任何时间,任何一天创建子类别,以及已经具有某些子类别的类别下的新子类别,并且律师将被置于其下。
  7. 图像是我目前正在进行的索引/主页的复制品,至少在上面的第6个上面任何时候生效,我希望使用循环来实现这个视图。

图解理解我想要做的事情:

我主页的图像说明

这是我在3个模型之间的关系

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 

我在这3个型号上的关联是否适合我提供的提示? 这非常令人困惑。

您不需要Subcategory模型/表,特别是如果它们具有相同的列。 您的categories表应具有parent_id列。 当类别具有指向另一个类别记录的parent_id值时,该类别是子类别。 具有NULL parent_id的类别是顶级类别。

 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 

注意:您应该创建一个迁移,将parent_id列添加到categories表中。 您可以删除子类别表。

现在创建一些类别(我假设有一个name列):

 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 

示例目录:

 <% 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 %> 

以上是一个简化的例子。 希望有所帮助。

更新

要增强表单以允许您创建子类别并分配其父类别,请使用填充top_level类别ID的选择菜单:

 <%= 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 %> 

如果不熟悉,请查看options_from_collection_for_select的文档。 它的作用是构建一个带有类别的选择菜单:id作为值,它们:name作为菜单中的文本。 确保将:parent_id添加到强参数中,以允许通过params[:category]进行质量分配。

在我的示例代码中, laywer错误只是一个错字,现在已经修复了。