创建或更新has_one ActiveRecord关联

时间:2012-01-13 00:03:16

标签: ruby-on-rails activerecord

我一直试图了解ActiveRecord个关联,但我碰到了一些砖墙,无论我查看ActiveRecord文档有多少,我都无法工作如何解决我的问题。

我有两个班级:

Property -> has_one :contract  
Contract -> belongs_to :property

在我的合同类中,我有一个create_or_update_from_xml

的方法

首先,我检查以确保有问题的财产存在。

property_unique_id = xml_node.css('property_id').text
      property = Property.find_by_unique_id(property_unique_id)
      next unless property

这就是我遇到困难的地方,我对合同有一些属性,我想做的是:

if property.contract.nil?
  # create a new one and populate it with attributes
else
  # use the existing one and update it with attributes

我知道如果它是原始SQL我会怎么做,但我无法理解主动调用方法。

任何通过此路障的提示都将受到极大的赞赏。

提前致谢。

3 个答案:

答案 0 :(得分:35)

if property.contract.nil?
  property.create_contract(some_attributes)
else
  property.contract.update_attributes(some_attributes)
end

应该做的伎俩。当您拥有has_onebelongs_to关联时,您将获得build_foocreate_foo方法(类似于Foo.new和Foo.create)。如果关联已经存在,则property.contract基本上只是一个正常的活动记录对象。

答案 1 :(得分:17)

使用ruby OR-Equal技巧

进行此操作的另一种方法
property.contract ||= property.build_contract
property.contract.update_attributes(some_attributes)

更新:

@KayWu是对的,上面的|| =技巧将在第一行创建合同对象,而不是仅仅构建它。另一种选择是

property.build_contract unless property.contract
property.contract.update_attributes(some_attributes)

答案 2 :(得分:9)

Property.all.each do |f|
  c = Contract.find_or_initialize_by(property_id: f.id)
  c.update(some_attributes)
end

我不知道这是否是最好的解决方案,但对我来说更简洁