您在这里有两个选择,具体取决于您的逻辑和视图与范围的关联程度。让我进一步解释一下。
第一个选择是确定控制器内的范围,正如其他响应已经解释的那样。我通常设置一个@scope 变量来在我的模板中获得一些额外的好处。
class Articles
before_filter :determine_scope
def index
@articles = @scope.all
# ...
end
protected
def determine_scope
@scope = if params[:category_id]
Category.find(params[:category_id]).articles
else
Article
end
end
end
@scope 变量的原因是您可能需要知道单个操作之外的请求范围。假设您想在视图中显示记录数。您需要知道您是否按类别过滤。在这种情况下,您只需调用@scope.count
or@scope.my_named_scope.count
而不是每次都重复检查 on params[:category_id]
。
如果您的视图(包含类别的视图和不包含类别的视图)非常相似,则此方法效果很好。但是,当按类别过滤的列表与没有类别的列表完全不同时会发生什么?这种情况经常发生:您的类别部分提供一些以类别为中心的小部件,而您的文章部分提供一些与文章相关的小部件和过滤器。此外,您的文章控制器有一些您可能想要使用的特殊 before_filters,但当文章列表属于某个类别时,您不必使用它们。
在这种情况下,您可能希望分离操作。
map.resources articles
map.resources categories, :collection => { :articles => :get }
articles_path # /articles and ArticlesController#index
category_articles_path(1) # /category/1/articles and CategoriesController#articles
现在按类别过滤的列表由 管理,CategoriesController
它继承所有控制器过滤器、布局、设置......而未过滤的列表由ArticlesController
.
这通常是我最喜欢的选择,因为通过额外的操作,您不必用大量的条件检查来弄乱您的视图和控制器。