RoR:模型多次引用自身

RoR: Model referencing itself multiple times

我有一个房间模型。每个房间有 6 个出口(北、东、南、西、上、下),我应该可以做 Room.first.nr 之类的事情,让房间位于第一个房间的北边。我制作的模型如下:

class Room < ApplicationRecord

  has_one :nr, class_name: 'Room', foreign_key: :id
  belongs_to :sr, class_name: 'Room'

  has_one :er, class_name: 'Room', foreign_key: :id
  belongs_to :wr, class_name: 'Room'

  has_one :sr, class_name: 'Room', foreign_key: :id
  belongs_to :nr, class_name: 'Room'

  has_one :wr, class_name: 'Room', foreign_key: :id
  belongs_to :er, class_name: 'Room'

  has_one :ur, class_name: 'Room', foreign_key: :id
  belongs_to :dr, class_name: 'Room'

  has_one :dr, class_name: 'Room', foreign_key: :id
  belongs_to :ur, class_name: 'Room'

end

但是,在 rails c

中执行此操作时
Room.create!(title:'sometitle', description:'somedescription', er: Room.first)

我明白了:

ActiveRecord::RecordInvalid: Validation failed: Sr must exist, Wr must exist, Nr must exist, Dr must exist, Ur must exist

我也玩过 inverse_of 没用。

这是我的迁移:

class CreateRooms < ActiveRecord::Migration[5.0]
  def change
    create_table :rooms do |t|
      t.string :title, null: false
      t.text :description, null: false

      t.integer :nr_id, null: true
      t.integer :er_id, null: true
      t.integer :sr_id, null: true
      t.integer :wr_id, null: true
      t.integer :ur_id, null: true
      t.integer :dr_id, null: true

      t.timestamps
    end

    add_index :rooms, :nr_id
    add_index :rooms, :er_id
    add_index :rooms, :sr_id
    add_index :rooms, :wr_id
    add_index :rooms, :ur_id
    add_index :rooms, :dr_id

  end
end

您的关联名称存在冲突(即 has_one :nrbelongs_to :nr)。应该类似于以下内容:

class Room < ApplicationRecord

  belongs_to :sr, class_name: 'Room'
  belongs_to :wr, class_name: 'Room'
  belongs_to :nr, class_name: 'Room'
  belongs_to :er, class_name: 'Room'
  belongs_to :dr, class_name: 'Room'
  belongs_to :ur, class_name: 'Room'

end

我认为您不再需要 has_one 关系。因为你已经可以用这些belongs_to

四面八方的房间了

好吧,花了点时间,但我想通了。

模型采用这种形式:

class Room < ApplicationRecord

  has_one :nr, class_name: 'Room', foreign_key: 'sr_id', inverse_of: :sr

  has_one :er, class_name: 'Room', foreign_key: 'wr_id', inverse_of: :wr

  has_one :sr, class_name: 'Room', foreign_key: 'nr_id', inverse_of: :nr

  has_one :wr, class_name: 'Room', foreign_key: 'er_id', inverse_of: :er

  has_one :ur, class_name: 'Room', foreign_key: 'dr_id', inverse_of: :dr

  has_one :dr, class_name: 'Room', foreign_key: 'ur_id', inverse_of: :ur

end

所以我能做到

a=Room.create(title:'the title', description: 'the description')
a.er = Room.find(1)
a.save

这也是正确的:

Room.find(1).wr == Room.last

谢谢@Jay-Ar Polidario