我在rails中使用default_scope来吸取任何值为is_deleted = true的东西(任何具有此值的东西都不应该显示,但我仍然希望将该行保留在数据库中)。但是有一个控制器动作应该实际取消删除(set is_deleted = false),但它失败了,因为正在应用default_scope。我的理解是default_scope仅在选择/创建记录时应用,但在更新时不应用(来源:http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html)。
在创建/构建记录时也会应用default_scope。更新记录时不会应用它。
我知道我可以使用.unscoped方法,但似乎这是违反直觉的。我误解了文档吗?
应用/模型/ post.rb
class Post < ActiveRecord::Base
default_scope where(:is_deleted => false)
应用/控制器/ posts_controller.rb
class PostsController < ApplicationController
def undelete
@post = Post.update(params[:id], :is_deleted => false)
render :action => :success if @post.save
end
错误
找不到帖子,其中id = 1 [WHERE“posts”。“is_deleted”='f']
答案 0 :(得分:4)
您提到的文档(The default_scope is also applied while creating/building a record. It is not applied while updating a record.
)中的行 - 表示default_scope属性应用于构建/创建的所有模型:
在您的情况下,所有新记录都将is_deleted
属性设置为false
但是在更新时,如果从db获取记录,则更改一个属性(例如title
),并调用save
- is_deleted
属性不会强制为{ {1}},就像在创作时发生的那样。
但您使用的false
方法(you can check it here)只在里面使用update
,它始终使用find
解决方案就是使用default_scope
方法
unscoped
答案 1 :(得分:1)
我认为你会对语义产生误解。 Rails必须先找到你的记录才能更新它。要让Rails找到记录,您需要使用.unscoped方法。要了解Rails如何应用范围值,您可以:
raise Post.find(:id => id, :is_deleted => true).to_sql
您应该看到类似的内容:
SELECT * FROM posts WHERE `id`=123 AND `is_deleted` = true AND `is_deleted` = false
.unscoped方法告诉Rails不要应用最后一个条件。即使您为同一字段提供了附加条件,Rails也不会跳过默认范围。