@elibinary
2016-09-10T10:33:36.000000Z
字数 3722
阅读 786
未分类
delete
delete_all
以下是文档中的例子:
# Delete a single rowTodo.delete(1)# Delete multiple rowsTodo.delete([2,3,4])
下面看下其源码实现:
# File activerecord/lib/active_record/relation.rbdef delete(id_or_array)where(primary_key => id_or_array).delete_allend
源码很简单,这个方法其实就是调用了 delete_all 方法
例子:
Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
destroy
destroy_all
例子:
# Destroy a single objectTodo.destroy(1)# Destroy multiple objectsTodo.destroy([1,2,3])
来看下源码实现
# File activerecord/lib/active_record/relation.rbdef destroy(id)if id.is_a?(Array)id.map { |one_id| destroy(one_id) }elsefind(id).destroyendend
源码中表示该方法会先实例化一个一个的对象再删除。
下面来看下 model 关联时的 :dependent option
对 has_many 来说
* 如果不设置 :dependent ,那么默认的就是 :nullify ,在这种模式下删除操作只会把 foreign keys 的值设为 NULL 而不会真正删除掉记录
例如:
class User < ActiveRecord::Basehas_many :posts # dependent: :nullify option by defaultenduser.posts# => #<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">]>user.posts.delete(Post.find(1))# or (other way)user.posts.delete(1)Post.find(1)# => #<Post id: 1, body: "aaa", user_id: nil, created_at: "2016-09-09 02:18:47", updated_at: "2016-09-09 02:18:47">user.posts.delete_alluser.posts.size# => 0Post.find(1, 2)# => [#<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 方法会被触发
class User < ActiveRecord::Basehas_many :posts, dependent: :destroyenduser.posts# => #<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">]>user.posts.delete(7,8)# => [#<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">]### DEBUG INFO# Post Load (0.4ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 AND #`posts`.`id` IN (7, 8)# (0.2ms) BEGIN# SQL (0.3ms) DELETE FROM `posts` WHERE `posts`.`id` = 7# SQL (0.2ms) DELETE FROM `posts` WHERE `posts`.`id` = 8# (43.4ms) COMMIT
当使用 delete_all 方法时,虽然设置了 :dependent 为 :destroy ,但实际上其策略却会是 :delete_all ,这时删除操作并不会将记录实例化, callback 方法也不会被触发,实际操作将会是一条 DELETE 语句
user.posts.delete_all### DEBUG INFO# SQL (0.7ms) DELETE FROM `posts` WHERE `posts`.`user_id` = 1
使用 delete 方法,记录会被真正删除,但是却不会调用其 destroy 方法,也不会触发 callbacks。(注意,如果参数传递的是 id 值,那么当此条目不存在时将会抛出异常 'ActiveRecord::RecordNotFound')
user.posts.delete(12)### DEBUG INFO# Post Load (0.4ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 AND #`posts`.`id` = 12 LIMIT 1# (0.2ms) BEGIN# SQL (0.3ms) DELETE FROM `posts` WHERE `posts`.`user_id` = 1 AND `posts`.`id` = 12# (0.6ms) COMMIT
这两个方法都会忽视掉 :dependent option