Rails has_one没有保存外键

时间:2012-12-27 18:57:35

标签: ruby-on-rails activerecord

我有以下表格

keyword
  keyword_id - PK
  description
  status_id - FK

keyword_status
  status_id - PK
  description

尝试在AR中对它们进行建模,并且在尝试保存我的测试时,它不会在关键字中保存状态ID。它们被映射为:

class Keyword < ActiveRecord::Base
  self.table_name = :keyword
  self.primary_key = :KEYWORD_ID  

  attr_writer :description
  attr_writer :keyword_status

  has_one :keyword_status, foreign_key: :STATUS_ID

end

class KeywordStatus < ActiveRecord::Base
  self.table_name = :keyword_status
  self.primary_key = :STATUS_ID
end

以及它破坏的代码(关键字状态由夹具填充)

keyword = Keyword.new
keyword.description = "keyword#{n}"
keyword.keyword_status = KeywordStatus.first
keyword.save

当调用keyword.save时,我无法在表关键字'STATUS_ID'中插入NULL

注意:我无法更改任何DDL

2 个答案:

答案 0 :(得分:2)

你的方向错了。它应该是关键字belongs_to status。一般规则是具有外键列的模型属于另一个模型。

答案 1 :(得分:2)

正如dstarh所说,外键关联是倒退的。在您的模型中,您只需要:

class Keyword < ActiveRecord::Base
  has_one :keyword_status
end

class KeywordStatus < ActiveRecord::Base
  belongs_to :keyword, :foreign_key => "status_id"
end

让协会工作。此外,在创建关联对象之前使用fixture设置KeywordStatus对象有点奇怪,但如果这是您需要的行为,则会起作用。另外,为什么不使用外键keyword_id并让rails为你处理它?

如果您想使用keyword_id代替status_id作为外键,请更新:

表格如下:

keyword
 id - PK
 description

keyword_status
 id - PK
 keyword_id - FK
 description

你的模特:

class Keyword < ActiveRecord::Base
  has_one :keyword_status
end

class KeywordStatus < ActiveRecord::Base
  belongs_to :keyword
end

希望这有帮助!

更新2:鉴于表格无法更改,关联必须有点倒退。我建议:

class Keyword < ActiveRecord::Base
  belongs_to :keyword_status
end

class KeywordStatus < ActiveRecord::Base
  has_many :keywords, :foreign_key => "status_id" 
end

我使用了很多作为关联,因为从所说的看起来关键字可以共享另一个关键字具有的状态。这也意味着您必须执行以下操作:

KeywordStatus.first.keywords = KeywordStatus.first.keywords.push(keyword)
KeywordStatus.save

而不是:

keyword.keyword_status = KeywordStatus.first

其运作方向与您想要的相反。正如您所看到的,这可能会让人感到非常困惑,所以如果可能的话,我会建议编写一个迁移来更改表(如果这是问题,可以对具有现有数据的表执行此操作)。我希望这有帮助!