代码之家  ›  专栏  ›  技术社区  ›  Scott

rails在创建具有一对多关系的模型实例时遇到问题

  •  2
  • Scott  · 技术社区  · 15 年前

    我想有很多地方我的设计可能会搞砸。不过,我对rails的经验非常有限。这在带有Postgres8.3的Rails2.3.2中发生。

    我们的数据库里有两张桌子。一个叫做“ survey “还有一个打电话来” survey_timepoint “。一个调查可以有多个时间点,所以 测量时间点 表中有一列名为“ survey_id “上面有fk约束。

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

    在我的rails模型中,我有:

    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 不会有事的。看来我不该这么做。我是否会被困在分别创建和保存每个对象以及将整个过程包装到事务中?这似乎很不讽刺。对我可能遗漏的任何必要信息深表歉意。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Kathy Van Stone    15 年前

    您可能需要检查正在发送的sql命令。它好像在添加 survey_timepoint 记录在 survey 记录。注意,您已经在处理两个数据库更改 调查 以及 测量时间点 -所以你应该用交易。

    你可以通过行动解决眼前的问题。 s.save! 在添加时间点之前(然后再次调用它)。我对rails功能的了解不够深入,不足以知道是否有一种更“railsy”的方法来完成这项工作,然后将其包装到事务中。

        2
  •  1
  •   Ethan    15 年前

    我刚刚做了一个实验,发现这对mysql很有用:

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

    我认为这对PostgreSQL同样有效。

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

    你也可以在一行上做到这一点:

    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