Rails 3:如何根据Controller的方法创建命名范围?

在我的ApplicationController我有demo_mode? method(当前登录的用户类型为“demo”时返回true )。

Post model具有publisher_id字段,该字段引用Users表。

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

底线:post p由“demo”用户发布,当且仅当:

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

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

  • “demo”用户发布的所有post,如果是demo_mode? == true demo_mode? == true
  • 非“演示”用户发布的所有post,如果是demo_mode? == false demo_mode? == false

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

使用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?) 

尝试这样的事情

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

如果我理解正确,演示状态由会话确定,因此只有控制器知道它。 另一方面,控制器(或可能是视图)是您想要查询范围的唯一位置。 如果所有这些都是正确的,我会向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在命名范围和标准查询界面之间没有太大区别。