Rails 4 - 在更新之前从另一个表中删除行

时间:2013-11-24 22:31:24

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

我的成员控制器中有以下代码:

def update
  @member.phone_numbers.destroy_all
  respond_to do |format|
    if @member.update(member_params)
      format.html { redirect_to @member, notice: 'Member was successfully updated' }
    else
      format.html { render action: 'edit' }
    end
  end
end

我必须在更新成员之前删除 phone_numbers 中的现有记录,因为必须再次插入电话号码(因为可能的订单更改和其他原因,但确实如此)没关系)。

问题是:它有效,但如果成员无法更新,则所有电话号码都将被删除。

如果 @ member.update 失败,可以采取哪些措施来避免此问题?

2 个答案:

答案 0 :(得分:2)

您可以考虑将电话号码标记为销毁,而不是实际删除它们。

@member.phone_numbers.map(&:mark_for_destruction)

然后,当你执行@ member.update时,它应该同时更新和销毁相关的电话号码。以下是#mark_for_destruction的API:http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html#method-i-mark_for_destruction

否则,您可以查看设置事务块。 API很好地解释了这一点:http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

答案 1 :(得分:1)

将其包装到一个帮助器方法中,该方法将语句包装到事务中并从控制器调用:

# Member Model
def delete_phone_numbers_and_update(params)
  Member.transaction do 
    phone_numbers.destroy_all
    update(params)
  end
end

# Controller
def update
  respond_to do |format|
    if @member.delete_phone_numbers_and_update(member_params)
      format.html { redirect_to @member, notice: 'Member was successfully updated' }
    else
      format.html { render action: 'edit' }
    end
  end
end