【问题标题】:Rails default_scope being applied to updateRails default_scope 被应用于更新
【发布时间】:2012-12-18 16:52:52
【问题描述】:

我在 rails 中使用 default_scope 来吸出任何具有 is_deleted = true 值的东西(任何具有该值的东西都不应显示,但我仍想将该行保留在数据库中)。但是有一个控制器操作实际上应该取消删除某些内容(设置 is_deleted = false),但它失败了,因为正在应用 default_scope。据我了解,default_scope 仅在选择/创建记录时应用,但在更新时不应用(来源:http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html)。

创建/构建记录时也会应用 default_scope。更新记录时不应用。

我知道我可以使用 .unscoped 方法,但这似乎违反直觉。我误解了文档吗?

app/models/post.rb

class Post < ActiveRecord::Base
  default_scope where(:is_deleted => false)

app/controllers/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']

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    您提到的文档中的一行 (The default_scope is also applied while creating/building a record. It is not applied while updating a record.) - 说 default_scope 属性应用于构建/创建的所有模型:

    在您的情况下,所有新记录都将 is_deleted 属性设置为 false

    但是在更新时,如果您从数据库中获取记录,请更改一个属性(例如title),然后调用save - is_deleted 属性不会被强制为false,因为它发生了在创作中。

    但是你使用的update方法(you can check it here)只是在内部使用find,它总是使用default_scope

    解决方案就是使用unscoped 方法

    class PostsController < ApplicationController
    def undelete
      @post = Post.unscoped.update(params[:id], :is_deleted => false)
      render :action => :success if @post.save
    end
    

    【讨论】:

    • 非常感谢您的解释,这很有道理:)
    【解决方案2】:

    我认为你对语义很感兴趣。 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 不会跳过默认范围,即使您为同一字段提供了附加条件。

    【讨论】:

    • 啊,我明白了。所以 Post.update() 实际上是先调用 Post.find() ?这很有意义 - 但是文档非常令人困惑,说它在更新时不使用 default_scope 。这意味着它永远不会工作,因为 update() 首先调用 find(),对吧?
    猜你喜欢
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多