如果存在更新列其他创建,但有棘手的部分(我认为)

时间:2014-12-29 12:50:31

标签: ruby-on-rails postgresql ruby-on-rails-4 postgresql-9.2

这是交易: 我正在创建一个rails RESTful API,用于在PostgreSQL数据库中存储信息,我正在使用Parent和Childs控制器以及Parent和Child模型(示例名称)。

我需要的是检查子记录是否已经存在,而不是id。我需要检查Child是否已经是具有相同“type”和“parent_id”的记录。

如果找到记录,我将需要更新列“值”,但添加新的“值”,而不是替换,如:

Child data 1: {type => type1, values => { info1 => info1, val1 => 1 }, parent_id => parent1}
Child data 2: {type => type1, values => { info2 => info2, val2 => 2 }, parent_id => parent1}

Final result: {type => type1, values => *[*{ info1 => info1, val1 => 1}, {info2 => info2, val2 => 2 }*]*, parent_id => parent1}    

我已经看过一些主题,我现在在儿童模型中有这个:

before_create :check_child_exists

private

def check_child_exists
    @child = Child.find_by_type_and_parent_id(self.type, self.parent_id)
    if @child != nil
        @child.update_attribute(:value, <*>) # <*> = hash + newhash (an array of hashes)
    end
end

任何人都可以帮我吗?我将不胜感激。 如果需要任何其他信息,请告诉我。

先谢谢,

1 个答案:

答案 0 :(得分:0)

def update_previous_child
  conditions = {type: self.type, parent_id: self.parent_id}

  if existing_child = Child.find_by(conditions) # or Child.where(conditions).last
    new_value = (existing_child.value || []) + [new_hash]
    existing_child.update_attribute(:value, new_value)
  end
end

那应该做你想要的。但是每次创建一个孩子时,只会更新最后一个孩子。如果要更新所有现有行,请执行以下操作:

def update_previous_children
  conditions = {type: self.type, parent_id: self.parent_id}

  Child.where(conditions).each do |existing_child|
    new_value = (existing_child.value || []) + [new_hash]
    existing_child.update_attribute(:value, new_value)
  end
end

如果您知道如何正确序列化新哈希,可以编写一些SQL以在update_all返回的ActiveRecord::Relation上使用where,而不是将其转换为数组并使用每个条目update_attribute