Rails在非主键

时间:2018-02-20 15:09:01

标签: ruby-on-rails activerecord activemodel

在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

我的目标是&#34;连接&#34; common_areasroot_areas - <{>在area_id上而非id - 以便单个根区域条目可以&#34;拥有&#34 ;多个共同领域。

例如美国(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而不是{{ 1}})。

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

1 个答案:

答案 0 :(得分: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