【问题标题】:Rails 3: How to create a named scope based on Controller's method?Rails 3:如何根据控制器的方法创建命名范围?
【发布时间】:2011-05-20 12:55:40
【问题描述】:

在我的ApplicationController 中,我有demo_mode? 方法(当当前登录的用户类型为“演示”时,它返回true)。

Post 模型有publisher_id 字段,它引用Users 表。

User 具有user_type 字段,其中一个可能的值是“demo”。

底线:帖子 p 由“演示”用户发布当且仅当:

User.find(p.publisher_id).user_type == "demo"

我想创建一个命名范围Post.relevant,它将返回:

  • 所有由“演示”用户发布的帖子,如果demo_mode? == true
  • 非“演示”用户发布的所有帖子,如果demo_mode? == false

您将如何创建这样一个命名范围?我应该将demo_mode? 移动到其他地方吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 named-scope


    【解决方案1】:

    使用 lambda 创建动态范围,并将会话信息保留在模型之外:

    在您的模型中:

    class Post < ActiveRecord::Base
      scope :relevant, lambda {|demo_mode|
         joins(:publisher).
         where("publishers.user_type #{demo_mode ? '' : 'NOT'} LIKE 'demo'")
      }
    end
    

    然后在控制器中:

    posts = Post.relevant(demo_mode?)
    

    【讨论】:

      【解决方案2】:

      试试这样的

      class Post < ActiveRecord::Base
      
          scope :relevant, joins("INNER JOIN users ON (users.user_type = 'demo')").where("publisher_id = users.id")
      
      end
      

      【讨论】:

      • 我看不出这是如何考虑demo_mode? 方法的?
      【解决方案3】:

      如果我理解正确,演示状态由会话确定,因此只有控制器知道它。另一方面,控制器(或者可能是视图)是您想要查询范围的唯一地方。如果所有这些都是正确的,我会像这样向 ApplicationController 添加一个方法:

      class ApplicationController < ActionController::Base
        def relevant_posts
          Post.joins(:publisher).
            where("publishers.user_type #{demo_mode? ? '' : 'NOT'} LIKE 'demo'")
        end
      
        ...
        helper_method :relevant_posts # if you want it to be available in views
      end
      

      从技术上讲,这不是一个命名范围。但是,Rails 3 在命名范围和标准查询接口之间没有太大区别。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-18
        • 1970-01-01
        • 1970-01-01
        • 2015-10-12
        • 1970-01-01
        • 1970-01-01
        • 2013-08-06
        • 1970-01-01
        相关资源
        最近更新 更多