[关闭]
@elibinary 2016-09-10T10:33:36.000000Z 字数 3722 阅读 721

Rails - Delete the records

未分类


ActiveRecord::Relation

delete
delete_all

以下是文档中的例子:

  1. # Delete a single row
  2. Todo.delete(1)
  3. # Delete multiple rows
  4. Todo.delete([2,3,4])

下面看下其源码实现:

  1. # File activerecord/lib/active_record/relation.rb
  2. def delete(id_or_array)
  3. where(primary_key => id_or_array).delete_all
  4. end

源码很简单,这个方法其实就是调用了 delete_all 方法

例子:

  1. Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
  2. Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
  3. Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all

destroy
destroy_all

例子:

  1. # Destroy a single object
  2. Todo.destroy(1)
  3. # Destroy multiple objects
  4. Todo.destroy([1,2,3])

来看下源码实现

  1. # File activerecord/lib/active_record/relation.rb
  2. def destroy(id)
  3. if id.is_a?(Array)
  4. id.map { |one_id| destroy(one_id) }
  5. else
  6. find(id).destroy
  7. end
  8. end

源码中表示该方法会先实例化一个一个的对象再删除。

ActiveRecord::Associations::CollectionProxy

下面来看下 model 关联时的 :dependent option
对 has_many 来说
* 如果不设置 :dependent ,那么默认的就是 :nullify ,在这种模式下删除操作只会把 foreign keys 的值设为 NULL 而不会真正删除掉记录

例如:

  1. class User < ActiveRecord::Base
  2. has_many :posts # dependent: :nullify option by default
  3. end
  4. user.posts
  5. # => #<ActiveRecord::Associations::CollectionProxy [#<Post id: 1, body: "aaa", user_id: 1, created_at: "2016-09-09 02:18:47", updated_at: "2016-09-09 02:18:47">, #<Post id: 2, body: "bbb", user_id: 1, created_at: "2016-09-09 02:18:58", updated_at: "2016-09-09 02:18:58">]>
  6. user.posts.delete(Post.find(1))
  7. # or (other way)
  8. user.posts.delete(1)
  9. Post.find(1)
  10. # => #<Post id: 1, body: "aaa", user_id: nil, created_at: "2016-09-09 02:18:47", updated_at: "2016-09-09 02:18:47">
  11. user.posts.delete_all
  12. user.posts.size
  13. # => 0
  14. Post.find(1, 2)
  15. # => [#<Post id: 1, body: "aaa", user_id: nil, created_at: "2016-09-09 02:18:47", updated_at: "2016-09-09 02:18:47">, #<Post id: 2, body: "bbb", user_id: nil, created_at: "2016-09-09 02:18:58", updated_at: "2016-09-09 02:18:58">]

当使用 delete 方法时,被删除记录会被实例化并且删除时 callback 方法会被触发

  1. class User < ActiveRecord::Base
  2. has_many :posts, dependent: :destroy
  3. end
  4. user.posts
  5. # => #<ActiveRecord::Associations::CollectionProxy [#<Post id: 7, body: "1", user_id: 1, created_at: "2016-09-09 06:20:17", updated_at: "2016-09-09 06:20:17">, #<Post id: 8, body: "2", user_id: 1, created_at: "2016-09-09 06:20:20", updated_at: "2016-09-09 06:20:20">, #<Post id: 9, body: "3", user_id: 1, created_at: "2016-09-09 06:20:23", updated_at: "2016-09-09 06:20:23">]>
  6. user.posts.delete(7,8)
  7. # => [#<Post id: 7, body: "1", user_id: 1, created_at: "2016-09-09 06:20:17", updated_at: "2016-09-09 06:20:17">, #<Post id: 8, body: "2", user_id: 1, created_at: "2016-09-09 06:20:20", updated_at: "2016-09-09 06:20:20">]
  8. ### DEBUG INFO
  9. # Post Load (0.4ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 AND #`posts`.`id` IN (7, 8)
  10. # (0.2ms) BEGIN
  11. # SQL (0.3ms) DELETE FROM `posts` WHERE `posts`.`id` = 7
  12. # SQL (0.2ms) DELETE FROM `posts` WHERE `posts`.`id` = 8
  13. # (43.4ms) COMMIT

当使用 delete_all 方法时,虽然设置了 :dependent 为 :destroy ,但实际上其策略却会是 :delete_all ,这时删除操作并不会将记录实例化, callback 方法也不会被触发,实际操作将会是一条 DELETE 语句

  1. user.posts.delete_all
  2. ### DEBUG INFO
  3. # SQL (0.7ms) DELETE FROM `posts` WHERE `posts`.`user_id` = 1

使用 delete 方法,记录会被真正删除,但是却不会调用其 destroy 方法,也不会触发 callbacks。(注意,如果参数传递的是 id 值,那么当此条目不存在时将会抛出异常 'ActiveRecord::RecordNotFound')

  1. user.posts.delete(12)
  2. ### DEBUG INFO
  3. # Post Load (0.4ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 AND #`posts`.`id` = 12 LIMIT 1
  4. # (0.2ms) BEGIN
  5. # SQL (0.3ms) DELETE FROM `posts` WHERE `posts`.`user_id` = 1 AND `posts`.`id` = 12
  6. # (0.6ms) COMMIT

这两个方法都会忽视掉 :dependent option

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注