【问题标题】:Why does destroy_all and delete_all not work consistently for an ActiveRecord::Relation and ActiveRecord::Associations::CollectionProxy?为什么 destroy_all 和 delete_all 对于 ActiveRecord::Relation 和 ActiveRecord::Associations::CollectionProxy 不能一致地工作?
【发布时间】:2015-02-26 02:16:57
【问题描述】:

为什么当尝试在ActiveRecord::Associations::CollectionProxy 的实例上调用delete_alldestroy_all 并传递条件时,会抛出ArgumentError: Valid values are :nullify or :delete_all 错误,而ActiveRecord::Relation#delete_all 不会?

当尝试给定关系时,例如delete_all,就会出现这种情况,例如MoviesActors 之间可能存在的关系。在这种情况下,给定一个Movie 实例,可能需要执行以下操作:

movie.actors.delete_all(id: [2,3,4])

上面的不行,报错。

他们的对手#destroy_all也是如此。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    尽管是老问题,但我认为我会放弃答案。

    ActiveRecord::RelationActiveRecord::Associations 工作方式不同,可能会很烦人。它们非常有用,但在使用 destroy 来确保您没有一个充满孤儿的数据库时。

    这说明了你想要做的事情。

    使用活动记录删除数据数组:

    YourApplication::Models::YourClass.destroy_all(selector: value)
    

    不要这样做:(此代码不正确)

    YourApplication::Models::YourClass.find(selector: value).destroy_all 
    

    删除已经返回的数组

    data_to_delete = YourApplication::Models::YourClass.find(selector: value).destroy_all
    data_to_delete.each(&:destroy)
    

    回到具体问题

    此代码不正确

    movie.actors.delete_all(id: [2,3,4])
    

    这里的问题是您使用 AR 关联返回一个数据数组,然后对该数据调用 .delete_all(然后希望 delete_all 的 args 将充当 SQL 类型 WHERE IN。遗憾的是,这不是 AR 的工作方式.)

    正确的做法

    actors.delete_all(args) 
    

    args 类似于 movie: 'titanic', id: [1,2,3]

    我希望对以后阅读本文的人有所帮助。使用关联删除时要非常小心,因为 Active Record 会自动杀死孤立数据。如果您不确定,删除是更安全的选择。

    【讨论】:

    • 我不太明白最后两个代码示例之间的区别。你能解释一下吗?
    【解决方案2】:

    虽然看起来他们应该表现相同,并遵循最小意外原则,但实际上表现得非常令人惊讶和不同:

    ActiveRecord::CollectionProxy#delete_all 及其对应的#destroy_alldependent 参数作为其参数,其默认值为nil。这与ActiveRecord::Relation#delete_all 的工作方式大不相同,ActiveRecord::Relation#delete_all 采用一组条件,例如可以传递给ActiveRecord::Base 子类的条件。

    因此,鉴于上面的Actor 模型,可以这样做:

    Actor.delete_all(id: [2,3,4])

    但是,可能无法通过 associatino 代理获取 Movie's 关联的 Actor 记录,然后在其上调用 delete_all

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多