我正在try 构建一个JobReport模型,该模型保存来自GoodJob作业(job)的返回值.我可以在其上建立关联的两个字段id和active_job_id有问题.Id字段设置为返回作业(job)类中的active_job_id:
# from good_job-3.12.1/app/models/good_job/job.rb
def id
active_job_id
end
Good_jobs.active_job_id字段没有唯一性约束,将其设置为外键会引发postgres错误.
我怎样才能链接这两个表呢?
下面是我用来创建JOB_REPORTS表的迁移:
class CreateJobReports < ActiveRecord::Migration[7.0]
def change
create_table :job_reports do |t|
t.text :report
t.uuid :good_job_id
t.timestamps
end
add_foreign_key :job_reports, :good_jobs, column: :good_job_id, primary_key: :id
end
end
我的JobReport模型:
class JobReport < ApplicationRecord
belongs_to :good_job, class_name: 'GoodJob::Job', foreign_key: 'id'
end
我的Good_job.rb初始值设定项包含:
GoodJob::Job.class_eval do
has_one :job_report, dependent: :destroy
end
当我创建一个JobReport、将其绑定到一个作业(job)并保存它时,Postgres抱怨该id在Good_Jobs中不存在,因为它试图使用active_job_id:
irb(main):001:0> jr = JobReport.new; gj = GoodJob::Job.last
=>
#<GoodJob::Job:0x00007ff6950cda30
...
irb(main):002:0> jr.good_job = gj
=>
#<GoodJob::Job:0x00007ff6950cda30
...
irb(main):003:0> jr.save
/usr/local/bundle/gems/activerecord-7.0.4.1/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `exec_params': PG::ForeignKeyViolation: ERROR: insert or update on table "job_reports" violates foreign key constraint "fk_rails_6135bfd69e" (ActiveRecord::InvalidForeignKey)
DETAIL: Key (good_job_id)=(fdc02e75-a06a-4727-b790-9a846f61ed7d) is not present in table "good_jobs".
/usr/local/bundle/gems/activerecord-7.0.4.1/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `exec_params': ERROR: insert or update on table "job_reports" violates foreign key constraint "fk_rails_6135bfd69e" (PG::ForeignKeyViolation)
DETAIL: Key (good_job_id)=(fdc02e75-a06a-4727-b790-9a846f61ed7d) is not present in table "good_jobs".
irb(main):004:0> gj.id
=> "fdc02e75-a06a-4727-b790-9a846f61ed7d"
irb(main):005:0> gj.active_job_id
=> "fdc02e75-a06a-4727-b790-9a846f61ed7d"
irb(main):006:0> gj.attributes["id"]
=> "edc27b66-975d-4017-a09f-2d0cec332a0c"
正如我前面提到的,如果我放弃ID列而切换到active_job_id列,Postgres说我不能将它用作外键b/c,没有唯一性约束.当然,我可以编辑GoodJob表,但我更喜欢使用GEM的插件形式,而不是篡改它来进行升级或诸如此类的事情.
编辑:我实现了Max的建议,但它仍在try 使用Good_jobs表的active_job_id列,而不是id列.
class JobReport < ApplicationRecord
belongs_to :good_job, class_name: 'GoodJob::Job', foreign_key: 'good_job_id', primary_key: 'id'
end
irb(main):010:0> jr = JobReport.new; gj = GoodJob::Job.last
=>
#<GoodJob::Job:0x00007f70ec430918
...
irb(main):011:0> jr.good_job = gj
=>
#<GoodJob::Job:0x00007f70ec430918
...
irb(main):012:0> jr.save
/usr/local/bundle/gems/activerecord-7.0.4.1/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `exec_params': PG::ForeignKeyViolation: ERROR: insert or update on table "job_reports" violates foreign key constraint "fk_rails_6135bfd69e" (ActiveRecord::InvalidForeignKey)
DETAIL: Key (good_job_id)=(fdc02e75-a06a-4727-b790-9a846f61ed7d) is not present in table "good_jobs".
/usr/local/bundle/gems/activerecord-7.0.4.1/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `exec_params': ERROR: insert or update on table "job_reports" violates foreign key constraint "fk_rails_6135bfd69e" (PG::ForeignKeyViolation)
DETAIL: Key (good_job_id)=(fdc02e75-a06a-4727-b790-9a846f61ed7d) is not present in table "good_jobs".
irb(main):013:0> gj.id
=> "fdc02e75-a06a-4727-b790-9a846f61ed7d"
irb(main):014:0> gj.active_job_id
=> "fdc02e75-a06a-4727-b790-9a846f61ed7d"
irb(main):015:0> gj.attributes['id']
=> "edc27b66-975d-4017-a09f-2d0cec332a0c"
下面是这两个表的模式:
development=# \d good_jobs
Table "public.good_jobs"
Column | Type | Collation | Nullable | Default
---------------------+--------------------------------+-----------+----------+-------------------
id | uuid | | not null | gen_random_uuid()
queue_name | text | | |
priority | integer | | |
serialized_params | jsonb | | |
scheduled_at | timestamp(6) without time zone | | |
performed_at | timestamp(6) without time zone | | |
finished_at | timestamp(6) without time zone | | |
error | text | | |
created_at | timestamp(6) without time zone | | not null |
updated_at | timestamp(6) without time zone | | not null |
active_job_id | uuid | | |
concurrency_key | text | | |
cron_key | text | | |
retried_good_job_id | uuid | | |
cron_at | timestamp(6) without time zone | | |
batch_id | uuid | | |
batch_callback_id | uuid | | |
Indexes:
"good_jobs_pkey" PRIMARY KEY, btree (id)
"index_good_jobs_on_cron_key_and_cron_at" UNIQUE, btree (cron_key, cron_at)
"index_good_jobs_jobs_on_finished_at" btree (finished_at) WHERE retried_good_job_id IS NULL AND finished_at IS NOT NULL
"index_good_jobs_jobs_on_priority_created_at_when_unfinished" btree (priority DESC NULLS LAST, created_at) WHERE finished_at IS NULL
"index_good_jobs_on_active_job_id" btree (active_job_id)
"index_good_jobs_on_active_job_id_and_created_at" btree (active_job_id, created_at)
"index_good_jobs_on_batch_callback_id" btree (batch_callback_id) WHERE batch_callback_id IS NOT NULL
"index_good_jobs_on_batch_id" btree (batch_id) WHERE batch_id IS NOT NULL
"index_good_jobs_on_concurrency_key_when_unfinished" btree (concurrency_key) WHERE finished_at IS NULL
"index_good_jobs_on_cron_key_and_created_at" btree (cron_key, created_at)
"index_good_jobs_on_queue_name_and_scheduled_at" btree (queue_name, scheduled_at) WHERE finished_at IS NULL
"index_good_jobs_on_scheduled_at" btree (scheduled_at) WHERE finished_at IS NULL
Referenced by:
TABLE "job_reports" CONSTRAINT "fk_rails_6135bfd69e" FOREIGN KEY (good_job_id) REFERENCES good_jobs(id)
development=# \d job_reports
Table "public.job_reports"
Column | Type | Collation | Nullable | Default
-------------+--------------------------------+-----------+----------+-----------------------------------------
id | bigint | | not null | nextval('job_reports_id_seq'::regclass)
report | text | | |
good_job_id | uuid | | |
created_at | timestamp(6) without time zone | | not null |
updated_at | timestamp(6) without time zone | | not null |
Indexes:
"job_reports_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"fk_rails_6135bfd69e" FOREIGN KEY (good_job_id) REFERENCES good_jobs(id)