@elibinary
2016-09-10T10:33:36.000000Z
字数 3722
阅读 721
未分类
delete
delete_all
以下是文档中的例子:
# Delete a single row
Todo.delete(1)
# Delete multiple rows
Todo.delete([2,3,4])
下面看下其源码实现:
# File activerecord/lib/active_record/relation.rb
def delete(id_or_array)
where(primary_key => id_or_array).delete_all
end
源码很简单,这个方法其实就是调用了 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 object
Todo.destroy(1)
# Destroy multiple objects
Todo.destroy([1,2,3])
来看下源码实现
# File activerecord/lib/active_record/relation.rb
def destroy(id)
if id.is_a?(Array)
id.map { |one_id| destroy(one_id) }
else
find(id).destroy
end
end
源码中表示该方法会先实例化一个一个的对象再删除。
下面来看下 model 关联时的 :dependent option
对 has_many 来说
* 如果不设置 :dependent ,那么默认的就是 :nullify ,在这种模式下删除操作只会把 foreign keys 的值设为 NULL 而不会真正删除掉记录
例如:
class User < ActiveRecord::Base
has_many :posts # dependent: :nullify option by default
end
user.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_all
user.posts.size
# => 0
Post.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::Base
has_many :posts, dependent: :destroy
end
user.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