【发布时间】:2020-11-09 22:19:49
【问题描述】:
使用 Ruby 2.7.0 和 Ruby on Rails 6.0.3.4
好的,假设我有两个模型 En 和 Em,我想在它们之间设置 N:M 关系。 Rails 文档有点稀缺,但它们advise the use 的create_join_table 迁移方法用于建立HABTM 关系。很快,运行rails g migration En Em 会给我一个迁移文件,其中包含
设置:
def change
create_join_table :ens, :ems do |t|
t.index [:en_id, :em_id]
t.index [:em_id, :en_id]
end
end
太好了。我还必须在我的 En 和 Em 模型中表明这种 N:M 关系,我这样做了:
class En < ApplicationRecord
has_and_belongs_to_many :ems
end
class Em < ApplicationRecord
has_and_belongs_to_many :ens
end
到目前为止看起来不错,我的简单测试也很有效:
m = Em.create
n = En.new
n.ems << m
n.save
En.find(n.id).ems # equals [em], unsurprisingly
问题
当我想用 ActiveRecord 做任何更花哨的事情时,比如通过 En 通过 Em 找到一些 En,我遇到了问题:
Em.where(ens: En.where(id: En.first)) #fails
En.where(ems: Em.where(id: Em.first)) #fails
Error:
ActiveRecord::UnknownPrimaryKey: Unknown primary key for table ems_ens in model En::HABTM_Ems.
因为create_join_table没有给我主键,所以我要自己加一个。没问题,再迁移一次就可以了,对吧?
def change
add_column :ems_ens, :id, :primary_key
end
Error:
DRb::DRbRemoteError: PG::UndefinedColumn: ERROR: column "en_id" does not exist
LINE 1: ...CT "ems".* FROM "ems" WHERE "ems"."id" IN (SELECT en_id FROM...
如果有帮助,我在这篇文章中做了quickly write a repo 来完全复制这种行为。 我肯定在这里遗漏了一些明显的东西,对吧? 我的工作代码也有类似的问题,但奇怪的是我遇到了更深层次的问题(比如En.where(ems: Em.where(ens: ...)),关系中的层次结构数据库不好玩)。
其他信息
由于一位评论者的请求,自动生成的schema.rb 和描述的表格。
ActiveRecord::Schema.define(version: 2020_11_09_210057) do
enable_extension "plpgsql"
create_table "ems", force: :cascade do |t|
t.string "mane"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "ems_ens", force: :cascade do |t|
t.bigint "en_id", null: false
t.bigint "em_id", null: false
t.index ["em_id", "en_id"], name: "index_ems_ens_on_em_id_and_en_id"
t.index ["en_id", "em_id"], name: "index_ems_ens_on_en_id_and_em_id"
end
create_table "ens", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
end
Table "public.ems_ens"
Column | Type | Collation | Nullable | Default
--------+--------+-----------+----------+-------------------------------------
en_id | bigint | | not null |
em_id | bigint | | not null |
id | bigint | | not null | nextval('ems_ens_id_seq'::regclass)
Indexes:
"ems_ens_pkey" PRIMARY KEY, btree (id)
"index_ems_ens_on_em_id_and_en_id" btree (em_id, en_id)
"index_ems_ens_on_en_id_and_em_id" btree (en_id, em_id)
Table "public.ems"
Column | Type | Collation | Nullable | Default
------------+--------------------------------+-----------+----------+---------------------------------
id | bigint | | not null | nextval('ems_id_seq'::regclass)
mane | character varying | | |
created_at | timestamp(6) without time zone | | not null |
updated_at | timestamp(6) without time zone | | not null |
Indexes:
"ems_pkey" PRIMARY KEY, btree (id)
Table "public.ens"
Column | Type | Collation | Nullable | Default
------------+--------------------------------+-----------+----------+---------------------------------
id | bigint | | not null | nextval('ens_id_seq'::regclass)
name | character varying | | |
created_at | timestamp(6) without time zone | | not null |
updated_at | timestamp(6) without time zone | | not null |
Indexes:
"ens_pkey" PRIMARY KEY, btree (id)
【问题讨论】:
-
你能从底层数据库中添加你的 schema.rb 的内容和一些 SQL DESCRIBE 语句吗?
-
嗨@3DPrintScanner,我将这两个都添加到原始问题中
标签: ruby-on-rails ruby rails-activerecord