【问题标题】:RoR: Model referencing itself multiple timesRoR:模型多次引用自身
【发布时间】:2016-02-09 20:34:25
【问题描述】:

我有一个房间模型。每个房间有 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

【问题讨论】:

    标签: ruby-on-rails activerecord rails-activerecord self-referencing-table


    【解决方案1】:

    您的关联名称有冲突(即has_one :nr 和belongs_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获得各个方向的房间了

    【讨论】:

    • 感谢您的回答。不幸的是,我仍然收到ActiveRecord::RecordInvalid: Validation failed: Sr must exist, Wr must exist, Nr must exist, Dr must exist, Ur must exist
    • 您的Room 模型中是否有唯一性验证?如果没有,您的ApplicationRecord 继承模型中是否有唯一性验证?您收到这些验证错误是因为您在代码中的某处对这些属性进行了唯一性验证。
    • 不,这很奇怪。但是,您为我指明了正确的方向。看我的回答。
    【解决方案2】:

    好的,花了一些时间,但我想通了。

    模型采用这种形式:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 2021-01-25
      • 2015-01-08
      • 1970-01-01
      • 2021-10-20
      • 2011-06-22
      • 1970-01-01
      相关资源
      最近更新 更多