【问题标题】:Rails add foreign key on non-primary keyRails 在非主键上添加外键
【发布时间】:2018-02-20 15:09:01
【问题描述】:

在 Rails 5.1 中,我有以下关系:

class RootArea < ApplicationRecord
  has_many :common_areas
end

class CommonArea < ApplicationRecord
  belongs_to :root_area, foreign_key: 'area_id', optional: true
end

以下是他们的迁移:

create_table "root_areas", force: :cascade do |t|
  t.integer "area_id"
  t.string "localname"
  t.string "globalname"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "common_areas", force: :cascade do |t|
  t.integer "area_id"
  t.string "localname"
  t.string "globalname"
  t.integer :root_area_id
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

我的目标是“连接”common_areasroot_areas -area_id 而不仅仅是 id- 这样单个根区域条目可能“具有”多个公共领域。

例如美国(RootArea)有加利福尼亚(CommonArea),德克萨斯(CommonArea)等。

我尝试使用迁移和外键来执行此操作,如下所示:

add_foreign_key :common_areas, :root_areas, primary_key: :area_id

虽然起初这似乎运作良好,但最终失败了:

>>> RootArea.create!(area_id: 1111, 
                     localname: ’test', 
                     globalname: ’test') # OK

>>> CommonArea.create!(area_id: 9999, 
                       localname: ’test', 
                       globalname: ’test') # OK

>>> RootArea.first.common_areas << CommonArea.first # Error

=> # SQL (44.3ms)  UPDATE "common_areas" SET "root_area_id" = $1, "updated_at" = $2 WHERE "common_areas"."id" = $3  [["root_area_id", 19], ["updated_at", "2018-02-20 14:45:52.545450"], ["id", 1]]

输出表明 Rails 尝试将CommonArea 的属性root_area_id 设置为RootArea 的主键(id 而不是area_id)。

例如在上面的示例中,生成的 sql 语句应该将 root_area_id 设置为 1111 而不是 19

【问题讨论】:

  • 您能分享一下您的班级和关系吗?
  • 已更新。世界
  • 谢谢。所以你没有名为'area'的类?使用has_many ... through 似乎更容易实现您想要的目标
  • 我不太明白为什么会有root_areascommon_areas 表。或者为什么这不是 HMT 等。
  • 所以,我正在尝试执行以下操作:即加利福尼亚 belongs_to 美国,德克萨斯 belongs_to 美国等。但我还需要能够执行 USA.common_areas 并吐出加利福尼亚,德克萨斯州等。最好的方法是什么?

标签: ruby-on-rails activerecord activemodel


【解决方案1】:

今晚晚些时候,我从 Rails IRC 频道寻求更多帮助,最终用户 dionysus69 向我指出了这个与我正在寻找的非常相似的 post。以供将来参考,这是最终的解决方案:

class RootArea < ApplicationRecord
  has_many :common_areas, foreign_key: 'root_area_id', primary_key: 'area_id'
end

class CommonArea < ApplicationRecord
  belongs_to :root_area, foreign_key: 'root_area_id', primary_key: 'area_id', optional: true
end

现在我可以成功了

>>  RootArea.first.common_areas << CommonArea.first

并将root_area_id 设置为正确的area_id 值,而不是id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-14
    • 2013-08-28
    • 2022-08-22
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    • 2023-03-29
    相关资源
    最近更新 更多