为什么destroy_all和delete_all对于ActiveRecord :: Relation和ActiveRecord :: Associations :: CollectionProxy不能一致地工作?

时间:2015-02-26 02:16:57

标签: ruby-on-rails activerecord

为什么尝试在delete_all的实例上调用destroy_allActiveRecord::Associations::CollectionProxy并传递条件时,会抛出ArgumentError: Valid values are :nullify or :delete_all错误,而{ {1}}不是吗?

在尝试ActiveRecord::Relation#delete_all时,如果delete_allMovies之间可能存在关系,则会出现这种情况。在这种情况下,给定Actors实例,可能需要执行以下操作:

Movie

以上不起作用,抛出错误。

他们的对手movie.actors.delete_all(id: [2,3,4])也是如此。

2 个答案:

答案 0 :(得分:2)

尽管有一个老问题我以为我会回答。

ActiveRecord :: Relation和ActiveRecord ::关联的工作方式不同,可能很烦人。虽然使用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(安培;:破坏)

返回特定问题

此代码不正确

  • 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会自动杀死孤儿数据。如果您不确定,删除是更安全的选择。

答案 1 :(得分:1)

虽然看起来他们应该表现得相同,并且遵循最少惊喜的原则,但实际上表现得非常惊人和不同:

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

因此,考虑到上面的Actor模型,可以这样做:

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

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