合并具有相同属性的Rails对象

时间:2017-01-26 15:21:28

标签: ruby-on-rails activerecord

我在创建可能具有相同(也是新创建的)子项的新记录时遇到问题。 为了简化操作,我们假设我有一个名为rules的表(如防火墙的访问控制列表中的规则)和一个名为ips的表,其中包含一个名为UNIQUE INDEX的ed属性ip_str

要创建Rule,需要来源Ip和目的地Ip

class Rule < ActiveRecord::Base
  belongs_to :src_ip,  class_name: Ip.name
  belongs_to :dest_ip, class_name: Ip.name
end

使用类似Rule的{​​{1}}并不罕见,在我们的情况下相当于

deny ip any any

这里显而易见的问题是,当我尝试保存src = Ip.where(ip_str: "any").first_or_initialize() dest = Ip.where(ip_str: "any").first_or_initialize() rule = Rule.new(src_ip: src, dest_ip: dest) rule.save() #=> throws error: duplicate entry 且数据库中没有Rule Ip时,Rails会保留两个单独的ip_str = "any" - 内存中的对象并尝试将它们相互保存。因此,保存第一个Ip成功,然后它会尝试保存它认为尚不存在的第二个Ip,并因Ip而导致错误。有没有办法告诉Rails在尝试保存之前在内存中合并“重复”对象?

上面给出的示例的一个明显的解决方案是以下

UNIQUE INDEX

可悲的是,现实世界要复杂得多,我可能会在不同的儿童模型中同时保存大量记录。是的,src = Ip.where(ip_str: "any").first_or_initialize() dest = Ip.where(ip_str: "any").first_or_initialize() dest = src if (src.ip_str == dest.ip_str) rule = Rule.new(src_ip: src, dest_ip: dest) rule.save() #=> always succeeds 绝对至关重要。

1 个答案:

答案 0 :(得分:1)

如果可以接受,可以在此使用first_or_create代替first_or_initialize

所以你保存了第一个Ip,然后你试着保存另一个(有相同的attrs),你只需要保存第一个。两个变量 - 一个对象。

相关问题