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在命名范围和标准查询界面之间没有太大区别。