Ruby Rails Activerecord - ID 在模型中交换

Ruby on Rails Activerecord - ids are Exchanged in Model

我在 Rails 4.2.0 和 Ruby 2.1.0 中使用 Ruby,并且我有一个自加入协会。这是我的迁移:

class CreateStateTemplates < ActiveRecord::Migration
  def change
    create_table :state_templates do |t|

      t.string :name

      t.references :next
      t.references :prev

      t.timestamps null: false
    end
  end
end

这是我的模型:

class StateTemplate < ActiveRecord::Base

  has_one :prev, :class_name => "StateTemplate", :foreign_key => "prev_id"
  belongs_to :state_template, :class_name => "StateTemplate", :foreign_key => "prev_id"
  has_one :next, :class_name => "StateTemplate", :foreign_key => "next_id"
  belongs_to :state_template, :class_name => "StateTemplate", :foreign_key => "next_id"

end

这里我填一些状态:

StateTemplate.find(1).update(:next => StateTemplate.find(2))
StateTemplate.find(2).update(:next => StateTemplate.find(3), :prev => StateTemplate.find(1))
StateTemplate.find(3).update(:next => StateTemplate.find(4), :prev => StateTemplate.find(2))
StateTemplate.find(4).update(:next => StateTemplate.find(5), :prev => StateTemplate.find(3))
StateTemplate.find(5).update(:prev => StateTemplate.find(4))

但是奇怪的事情发生了。当我从 StateTemplate 中取出一条记录并将其放在 concole 上时,我得到了这个:

2.1.0 :007 > StateTemplate.find(2)
  StateTemplate Load (0.1ms)  SELECT  "state_templates".* FROM "state_templates" WHERE "state_templates"."id" = ? LIMIT 1  [["id", 2]]
 => #<StateTemplate id: 2, name: "two", next_id: 1, prev_id: 3, created_at: "2017-07-22 11:51:30", updated_at: "2017-07-22 11:51:30"> 

这不对,因为 next_id 必须是 3,但是当我提到下一个状态时,我得到了这个:

2.1.0 :008 > StateTemplate.find(2).next
  StateTemplate Load (0.1ms)  SELECT  "state_templates".* FROM "state_templates" WHERE "state_templates"."id" = ? LIMIT 1  [["id", 2]]
  StateTemplate Load (0.0ms)  SELECT  "state_templates".* FROM "state_templates" WHERE "state_templates"."next_id" = ? LIMIT 1  [["next_id", 2]]
 => #<StateTemplate id: 3, name: "three", next_id: 2, prev_id: 4, created_at: "2017-07-22 11:51:30", updated_at: "2017-07-22 11:51:30"> 

这是对的。这是我的问题:为什么交换了记录中的 ID,但引用了正确的记录?

两个 belongs_to 协会具有相同的名称 (:state_template),但它们不需要具有不同的名称。此外,我认为 prevnext 指向 self 而不是指向链接模板有点令人困惑。

我会这样改变关联:

belongs_to :next, class_name: 'StateTemplate'
belongs_to :prev, class_name: 'StateTemplate'

has_one :predecessor, foreign_key: 'next_id', class_name: 'StateTemplate'
has_one :successor,   foreign_key: 'prev_id', class_name: 'StateTemplate'

这甚至可以简化。因为如果模板有 belongs_to :next,那么反向 has_one 会自动成为 prev。因此从该模型中删除 prev_id 并仅使用以下内容:

belongs_to :next, class_name: 'StateTemplate'
has_one :prev, foreign_key: 'next_id', class_name: 'StateTemplate'