假设您有两条定义的路线:
map.resources articles
map.resources categories, :has_many => :articles
两者都可以通过助手/路径访问
articles_path # /articles
category_articles_path(1) # /category/1/articles
如果你访问/articles
, index
行动来自ArticlesController
被执行。
如果你访问/category/1/articles
, index
行动来自ArticlesController
也被执行。
那么,根据调用路由有条件地仅选择范围内的文章的最佳方法是什么?
#if coming from the nested resource route
@articles = Articles.find_by_category_id(params[:category_id])
#else
@articles = Articles.all
这里有两种选择,具体取决于您的逻辑和视图与范围的关联程度。
让我进一步解释一下。
第一个选择是确定控制器内的范围,正如其他响应已经解释的那样。我通常设置一个 @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
而不是每次都重复检查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
.
这通常是我最喜欢的选择,因为通过额外的操作,您不必用大量的条件检查来弄乱您的视图和控制器。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)