Rails无法创建具有一对多关系的模型实例

时间:2009-07-23 19:22:16

标签: ruby-on-rails ruby postgresql activerecord

我认为有很多地方我的设计可能会搞砸了。我对Rails的经验非常有限。这种情况发生在Rails 2.3.2和Postgres 8.3中。

我们的数据库中有两个表。一个名为“survey”,一个名为“survey_timepoint”。调查可以有多个时间点,因此在survey_timepoint表中有一个名为“survey_id”的列,其上有一个fk约束。

我还认为我应该提到这些表不是使用rails迁移创建的,尽管它们遵循rails命名约定。我怀疑AR没有预料到该列的约束,也不知道如何处理这种情况。

在我的导轨型号中,我有:

has_many :survey_timepoint 

belongs_to :survey

如果我这样做:

s = Survey.new
s.survey_timepoint.push SurveyTimepoint.new
s.save!

我明白了:

ActiveRecord::StatementInvalid: PGError: ERROR:  insert or update on table "survey_timepoints" violates foreign key constraint "survey_timepoints_fk"
DETAIL:  Key (survey_id)=(59) is not present in table "surveys"

我假设如果我在survey_timepoint.survey_id上删除了那个fk约束,它就可以了。看来我不应该有。我是否会被困在分别创建和保存每个对象并将整个过程包装在事务中?这似乎相当不合理。对我可能遗漏的任何必要信息表示歉意。

2 个答案:

答案 0 :(得分:1)

您可能想要检查正在发送的SQL命令。它似乎是在survey_timepoint记录之前添加survey记录。请注意,您已经在处理两个数据库更改 - surveysurvey_timepoint - 因此您应该使用事务。

您可以在添加时间点之前执行s.save!来解决当前问题(然后再次调用它)。我对Rails功能的了解还不够深入,无法知道是否有更“顽固”的方法,然后将其包装在事务中。

答案 1 :(得分:1)

我刚刚进行了实验,发现这适用于MySQL:

s = Survey.new()
s.survey_timepoints << SurveyTimepoint.new  # Note "survey_timepoints" (plural)
s.save!

我认为它对PostgreSQL同样有效。

它执行两次插入,首先是Survey,然后是时间点,并将它们包装在事务中。

您也可以在一行中完成所有操作:

Survey.create!({:name=>'New Survey', :survey_timepoints => [SurveyTimepoint.new]})

顺便说一句,要使ActiveRecord正常工作,您必须确保您的单数和复数。 (如果你想打破预期的形式,你需要告诉AR你正在做那个 - 另外一个主题。)

你的桌子应该是:

surveys
-------
# ...

survey_timepoints
-----------------
survey_id
# ...

在你的模特中,你有:

class Survey < ActiveRecord::Base
  has_many :survey_timepoints
  # etc...
end

class SurveyTimepoint < ActiveRecord::Base
  belongs_to :survey
end