创建或更新has_one ActiveRecord关联

Sti*_*eal 26 activerecord ruby-on-rails

我一直在努力ActiveRecord探索协会,但我已经碰到了一些砖墙,无论我查看ActiveRecord文档多少,我都无法解决如何解决问题.

我有两节课:

Property -> has_one :contract  
Contract -> belongs_to :property
Run Code Online (Sandbox Code Playgroud)

在我的契约类中,我有一个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
Run Code Online (Sandbox Code Playgroud)

这就是我遇到困难的地方,我有合同的属性哈希,我想要做的是:

if property.contract.nil?
  # create a new one and populate it with attributes
else
  # use the existing one and update it with attributes
Run Code Online (Sandbox Code Playgroud)

我知道如果它是原始SQL我会怎么做,但我无法理解主动的ActiveRecord方法.

任何通过这个路障的提示都将受到极大的赞赏.

提前致谢.

Fre*_*ung 35

if property.contract.nil?
  property.create_contract(some_attributes)
else
  property.contract.update_attributes(some_attributes)
end
Run Code Online (Sandbox Code Playgroud)

应该做的伎俩.如果你有一个has_one或者一个belongs_to关联,那么你得到build_foocreate_foo方法(就像Foo.new和Foo.create).如果关联已经存在,那么property.contract基本上只是一个普通的活动记录对象.


Kin*_*ani 20

只是另一种使用ruby OR-Equal技巧的方法

property.contract ||= property.build_contract
property.contract.update_attributes(some_attributes)
Run Code Online (Sandbox Code Playgroud)

更新:

@KayWu是对的,上面的|| = trick将在第一行创建契约对象,而不是仅仅构建它.另一种选择

property.build_contract unless property.contract
property.contract.update_attributes(some_attributes)
Run Code Online (Sandbox Code Playgroud)

  • 将对象分配给has_one关联时,将自动保存该对象,这可能会破坏验证.http://guides.rubyonrails.org/association_basics.html#has-one-association-reference使用property.build_contract,除非是property.contract. (3认同)

小智 9

Property.all.each do |f|
  c = Contract.find_or_initialize_by(property_id: f.id)
  c.update(some_attributes)
end
Run Code Online (Sandbox Code Playgroud)

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