自联接Rails表允许仅以一种方式添加关联

时间:2017-05-21 12:27:02

标签: ruby-on-rails associations self-join

我在代码中创建自引用关联时遇到问题。一般来说,我的想法是我有各种研讨会类别,这个类别可能需要另一个(你必须完成第一个类别才能注册第二个)。我的模型有以下代码:

class WorkshopCategory < ApplicationRecord
  has_many :category_requirements, foreign_key: 'category_id', class_name: 'CategoryRequirement'
  has_many :requirements, through: :category_requirements
end

class CategoryRequirement < ApplicationRecord
  belongs_to :category, foreign_key: 'category_id', class_name: 'WorkshopCategory'
  belongs_to :requirement, foreign_key: 'requirement_id', class_name: 'WorkshopCategory'
end

并在他们的表移植之后:

class CreateWorkshopCategories < ActiveRecord::Migration[5.0]
  def change
    create_table :workshop_categories do |t|
       # some fields for workshop_categories
    end
  end
end

class CreateCategoryRequirements < ActiveRecord::Migration[5.0]
  def change
    create_table :category_requirements do |t|
      t.integer :category_id, index: true
      t.integer :requirement_id
    end
  end
end

我创建了一些种子,我遇到了以下问题:

WorkshopCategory.find(2).requirements.create(requirement_id: 1)

导致错误&#39; ActiveModel :: UnknownAttributeError:未知属性&#39; requirement_id&#39; for WorkshopCategory&#39;。

,同时:

CategoryRequirement.create(category_id: 2, requirement_id: 1)

正常工作,然后WorkshopCategory.find(2).requirements也正确返回id为1的WorkshopCategory作为其要求。

我可能误解了Rails指南,因为我是初学者,但据我所知,两种方式都应该正常工作,对吗?如果是,那么我的代码有什么问题?为什么WorkshopCategory.find(2).requirements.create()在WorkshopCategory模型而不是CategoryRequirement上运行?

1 个答案:

答案 0 :(得分:0)

基本上,我有一个错误的假设。我根据这里提供的代码编写了我的关联代码:

class Person < ActiveRecord::Base
   has_many :friendships, :foreign_key => "person_id", 
      :class_name => "Friendship"

   has_many :friends, :through => :friendships
end

class Friendship < ActiveRecord::Base
   belongs_to :person, :foreign_key => "person_id", :class_name => "Person"
   belongs_to :friend, :foreign_key => "friend_id", :class_name => "Person"  
end

虽然你可以使用Person.find(1).friends访问sb的朋友,但是你不能做Person.find(1).friends.create(friend_id:2),就像在这种情况下一样你试图创造一个新人 - 而我们需要的是创造一种友谊。因此,在上述代码的情况下,2种创建关联的方式是:

Person.find(1).friendships.create(friend_id: 2)
# and
Friendships.create(person_id: 1, friend_id: 2)

在我的情况下,这些是:

WorkshopCategory.find(2).category_requirements.create(requirement_id: 1)
# and
CategoryRequirement.create(category_id: 2, requirement_id: 1)