【问题标题】:Do not raise ActiveRecord::RecordNotFound if nested attributes marked for destruction do not exist如果标记为销毁的嵌套属性不存在,则不要引发 ActiveRecord::RecordNotFound
【发布时间】:2020-07-01 12:14:27
【问题描述】:

我正在使用 Rails nested attributesallow_destroy: true。如果我这样称呼:

deck.update(deck_items_attributes: { id: 1000, _destroy: true })

并且 ID 为 1000deck_item 不存在 Rails 引发异常 ActiveRecord::RecordNotFound

有没有办法告诉 Rails 不要抛出异常而忽略该记录?

【问题讨论】:

  • 我看到的唯一方法是重写您的Deck 模型的方法#update
  • @AlexGolubenko 我不明白你为什么删除你的答案。你在那里 75%。所缺少的只是检查属性是否存在。
  • @max 我已经在我的本地检查过,reject_if 没有在update 上运行,也许我错过了一些东西,但是..

标签: ruby-on-rails ruby nested-attributes accepts-nested-attributes


【解决方案1】:

您总是可以使用 begin rescue 来处理此类异常

begin
  deck.update(deck_items_attributes: { id: 1000, _destroy: true })
rescue ActiveRecord::RecordNotFound => e
  puts custom_error_msg
end

【讨论】:

  • 是的,但我希望其他属性仍保存在数据库中。
【解决方案2】:

如果记录不存在,请使用reject_if: 选项删除属性哈希:

accepts_nested_attributes_for :deck_items,
   reject_if: :deck_item_does_not_exist?

private
def deck_item_does_not_exist?(attributes)
  if attributes["id"].present? && attributes["_destroy"].present? 
    DeckItem.where(id: attributes["id"]).none?
  else
    false
  end
end

【讨论】:

  • @Pioz 是的,它实际上会生成 N+1 个查询。如果您渴望加载/包含关联并检查它是否存在,则可以避免这种情况。虽然它超出了原始问题的范围,但我避免了它,因为我对你的关联一无所知。随时提出单独的后续问题。
  • 您也可以使用!deck_item_ids.include?(attributes["id"]),Rails 应该缓存一次获取所有 id 的查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多