Rails delete_all 与 destroy_all的区别

来源:互联网 发布:神话网络电话卡骗局 编辑:程序博客网 时间:2024/06/07 03:57

Rails delete 与 destroy的区别

阅读文档,你将了解到:

  • ActiveRecord::Relation 和 ActiveRecord::Associations::CollectionProxy 的区别
  • ActiveRecord::Relation中delete和destroy的区别
  • ActiveRecord::Associations::CollectionProxy中delete和destroy的区别

ActiveRecord::Relation 和 ActiveRecord::Associations::CollectionProxy 的区别

说明

ActiveRecord::Relation中讲到的delete和destroy是指对当前对象进行的删除操作,
而ActiveRecord::Associations::CollectionProxy中则是对当前对象的关联对象进行的删除操作

关于Relation

NOTE:
1. 惰性加载( Lazy Loading )
数据库并没有执行查询的动作,只有当真正使用这些数据的时候才会去查询数据库。
2. 可以链式操作
Uers.where().where().order()….

关于Associations::CollectionProxy

NOTE:
has_many, has_one, belongs_to等关联操作

ActiveRecord::Relation

说明

简单说明一下,delete和destroy的区别在于
  1. delete直接在数据库执行一条sql语句;
  2. delete效率高于destroy(因为1);
  3. delete绕开业务逻辑的callback(使用时,需注意参照完整性约束)
  4. destroy需要将对象实例化
  5. destroy需要将对象一条一条删除(因为1)
  6. destroy耗费时间,因为每一条都需要执行:实例化,callback,删除
  7. destroy会把关联的对象的外键设为nil

delete(id_or_array)

Deletes the row with a primary key matching the id argument, using a SQL DELETE statement, and returns the number of rows deleted. Active Record objects are not instantiated, so
the object’s callbacks are not executed, including any :dependent association options.

You can delete multiple rows at once by passing an Array of ids.

NOTE:
Although it is often much faster than the alternative, destroy, skipping callbacks might bypass business logic in your application that ensures referential integrity or performs other essential jobs.

# Delete a single rowTodo.delete(1)# Delete multiple rowsTodo.delete([2,3,4])

delete_all()

Deletes the records without instantiating the records first, and hence not calling the #destroy method nor invoking callbacks. This is a single SQL DELETE statement that goes straight to the database, much more efficient than destroy_all. Be careful with relations though, in particular :dependent rules defined on associations are not honored. Returns the number of rows affected.
Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all

Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent associations or call your before_* or after_destroy callbacks, use the destroy_all method instead.

If an invalid method is supplied, delete_all raises an ActiveRecordError:
Post.limit(100).delete_all# => ActiveRecord::ActiveRecordError: delete_all doesn't support limit

destroy(id)

Destroy an object (or multiple objects) that has the given id. The object is instantiated first, therefore all callbacks and filters are fired off before the object is deleted. This method is less efficient than delete but allows cleanup methods and other actions to be run.

This essentially finds the object (or multiple objects) with the given id, creates a new object from the attributes, and then calls destroy on it.

NOTE:
Paramter Can be either an Integer or an Array of Integers.

# Destroy a single objectTodo.destroy(1)# Destroy multiple objectstodos = [1,2,3]Todo.destroy(todos)

destroy_all()

Destroys the records by instantiating each record and calling its #destroy method. Each object’s callbacks are executed (including :dependent association options). Returns the collection of objects that were destroyed; each will be frozen, to reflect that no changes should be made (since they can’t be persisted).

NOTE:
Instantiation, callback execution, and deletion of each record can be time consuming when you’re removing many records at once. It generates at least one SQL DELETE query per record (or possibly more, to enforce your callbacks). If you want to delete many rows quickly, without concern for their associations or callbacks, use delete_all instead.

Person.where(age: 0..18).destroy_all

ActiveRecord::Associations::CollectionProxy

delete(*records)

Deletes the records supplied from the collection according to the strategy specified by the :dependent option. If no :dependent option is given, then it will follow the default strategy. Returns an array with the deleted records.

For has_many :through associations, the default deletion strategy is :delete_all.

For has_many associations, the default deletion strategy is :nullify. This sets the foreign keys to NULL.
class Person < ActiveRecord::Base  has_many :pets # dependent: :nullify option by default  end  person.pets.size # => 3  person.pets# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.delete(Pet.find(1))# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]person.pets.size # => 2person.pets# => [#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]Pet.find(1)# => #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>

delete_all(dependent = nil)

Deletes all the records from the collection according to the strategy specified by the :dependent option. If no :dependent option is given, then it will follow the default strategy.

For has_many :through associations, the default deletion strategy is :delete_all.

For has_many associations, the default deletion strategy is :nullify. This sets the foreign keys to NULL.
class Person < ActiveRecord::Base  has_many :pets # dependent: :nullify option by default  end  person.pets.size # => 3  person.pets# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.delete_all# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.size # => 0person.pets      # => []Pet.find(1, 2, 3)# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>,#       #<Pet id: 2, name: "Spook", person_id: nil>,#       #<Pet id: 3, name: "Choo-Choo", person_id: nil>#]

Both has_many and has_many :through dependencies default to the :delete_all strategy if the :dependent option is set to :destroy. Records are not instantiated and callbacks will not be fired.

class Person < ActiveRecord::Base  has_many :pets, dependent: :destroy  end  person.pets.size # => 3  person.pets# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.delete_allPet.find(1, 2, 3)# => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)

If it is set to :delete_all, all the objects are deleted without calling their destroy method.

class Person < ActiveRecord::Base  has_many :pets, dependent: :delete_all  end  person.pets.size # => 3  person.pets# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.delete_allPet.find(1, 2, 3)# => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)

destroy(*records)

Destroys the records supplied and removes them from the collection. This method will always remove record from the database ignoring the :dependent option. Returns an array with the removed records.
  class Person < ActiveRecord::Base    has_many :pets    end    person.pets.size # => 3    person.pets# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.destroy(Pet.find(1))# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]person.pets.size # => 2person.pets# => [#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.destroy(Pet.find(2), Pet.find(3))# => [#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.size  # => 0person.pets       # => []Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)

You can pass Integer or String values, it finds the records responding to the id and then deletes them from the database.
person.pets.size # => 3person.pets# => [#       #<Pet id: 4, name: "Benny", person_id: 1>,#       #<Pet id: 5, name: "Brain", person_id: 1>,#       #<Pet id: 6, name: "Boss",  person_id: 1>#]person.pets.destroy("4")# => #<Pet id: 4, name: "Benny", person_id: 1>person.pets.size # => 2person.pets# => [#       #<Pet id: 5, name: "Brain", person_id: 1>,#       #<Pet id: 6, name: "Boss",  person_id: 1>#]person.pets.destroy(5, 6)# => [#       #<Pet id: 5, name: "Brain", person_id: 1>,#       #<Pet id: 6, name: "Boss",  person_id: 1>#]person.pets.size  # => 0person.pets       # => []Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)

destroy_all()

Deletes the records of the collection directly from the database ignoring the :dependent option. Records are instantiated and it invokes before_remove, after_remove , before_destroy and after_destroy callbacks.
class Person < ActiveRecord::Base  has_many :pets  end  person.pets.size # => 3  person.pets# => [#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,#       #<Pet id: 2, name: "Spook", person_id: 1>,#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>#]person.pets.destroy_allperson.pets.size # => 0person.pets      # => []Pet.find(1) # => Couldn't find Pet with id=1
原创粉丝点击