【问题标题】:How to destroy a database record if it fails uniqueness validation?如果唯一性验证失败,如何销毁数据库记录?
【发布时间】:2018-04-30 20:19:03
【问题描述】:

如果更新属性时唯一性验证失败,我希望能够销毁数据库记录。例如,如果我尝试将记录的字段更新为另一个具有唯一性验证且已存在于数据库中的另一条记录中的值,则应销毁正在更新的原始对象。

我曾尝试使用after_validation 回调来调用销毁对象的函数,但是,ActiveRecord 不断回滚并返回false,我不知道为什么。我认为这可能与唯一性验证有关,但是不确定。

我正在使用 Rails 5 和 ActiveRecord 与数据库交互。

下面是一个例子:

class Question
 validates :name, presence: true, uniqueness: true

 after_validation :destroy

 def destroy
  if self.errors.any?
   self.destroy
  end
 end

验证只针对对象的一个​​字段

【问题讨论】:

  • 我不知道如何在模型级别做到这一点,但是控制器级别呢? record.destroy if ! record.save
  • 我不会为您的自定义函数提供与 ActiveRecord 方法相同的名称:尝试将其重命名为 destroy_if_invalid 可能吗?
  • @MarcusChristiansen 如果不编写一些示例代码进行测试,我真的无能为力,所以我出去了。但是如果重复是问题,你总是可以添加一个辅助方法destroy_if_not_unique!,它会调用我上面的例子
  • 一个好的经验法则是在使其完美之前先让其发挥作用。如果你被困在完美的解决方案上,那就让它尽可能地发挥作用。稍后,您可能会找到解决方案并能够替换您的代码
  • @MarcusChristiansen 我会做出比这更强烈的声明:通常,由于无限循环,这个错误会导致StackTooDeep 异常!有了 Rails 的动态元编程,所有的赌注都没有了,但我无法想象会发生什么好事......

标签: ruby-on-rails ruby-on-rails-5


【解决方案1】:

也许你可以在控制器层做到这一点

example_controller.rb

def update
  if @question.update(params.require(:question).permit(:name))
     ...
  else
    @question.destroy if @question.errors.added?(:name, : uniqueness)
  end
end

【讨论】:

    【解决方案2】:

    尝试在调用destroy之前检查delete方法中有多少问题:

    def delete
      if Question.where(name: self.name).count > 1
        self.destroy
      end
    end
    

    【讨论】:

    • OP 希望验证发生并且只有在验证失败时才销毁。您的代码将绕过所有验证
    • @CarlMarkham 您现在可以检查我的答案吗?如果是这种情况,请删除您的 -1 票。谢谢。
    • 我在您编辑时检查过。 OP想要使用验证,你的答案不使用验证并添加了一个不理想的额外方法
    • @CarlMarkham 当然,但这是解决问题的一种方法,而且这是他的项目,所以他可以决定这种情况是否“理想”。抱歉,如果您不喜欢我的回答,我同意它并未涵盖所有要点,但这是一个开始,您的反对票现在看来有些夸张。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    相关资源
    最近更新 更多