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

Afo*_*umi 3 ruby ruby-on-rails associations model-associations ruby-on-rails-4

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

提示(如果我的协会没问题,你可以有一个线索)

  1. 在类别表上,我不希望在类别表上看到引用子类别的列.
  2. 在子类别表上,我不希望在Subcategories表上看到引用类别的列.
  3. 并非所有类别都有子类别.即一些没有如图所示的子类别.
  4. 我有2个单独的表单创建类别和子类别.
  5. 我将category_id和subcategory_id添加为我的律师表中的外键.这样我就可以在创建时选择律师形式,律师将在图像中尽快选择类别或子类别.
  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
Run Code Online (Sandbox Code Playgroud)

我对那3个型号的关联是否适合我提供的提示?这非常令人困惑.

Die*_*zar 5

您不需要Subcategory模型/表,特别是如果它们具有相同的列.你的categories桌子应该有一个parent_id专栏.当类别具有parent_id指向另一个类别记录的值时,该类别是子类别.带有a 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
Run Code Online (Sandbox Code Playgroud)

注意:您应该创建迁移以将parent_id列添加到类别表.您可以删除子类别表.

现在创建一些类别(我假设有一个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
Run Code Online (Sandbox Code Playgroud)

示例目录:

<% 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 %>
Run Code Online (Sandbox Code Playgroud)

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

更新

要增强表单以允许您创建子类别并指定其父类别,请使用填充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 %>
Run Code Online (Sandbox Code Playgroud)

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

laywer错误只是在我的示例代码中的错字,它现在固定.

  • 完善.很好,干净+1 (2认同)
  • @AfolabiOlaoluwaAkinwumi用另一个例子更新了答案. (2认同)