Rails:嵌套资源冲突,如何根据调用的路由来范围化索引操作 [英] Rails: Nested resources conflict, how to scope the index action depending on the called route

查看:73
本文介绍了Rails:嵌套资源冲突,如何根据调用的路由来范围化索引操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下,您有两条定义的路线:

Imagine you have two defined routes:

map.resources articles
map.resources categories, :has_many => :articles

均可通过助手/路径访问

both accessible by helpers/paths

articles_path # /articles
category_articles_path(1) # /category/1/articles

如果您访问 / articles ,则 index 操作

如果您访问 / category / 1 / articles ,<也执行了 ArticlesController 中的code> index 操作。

if you visit /category/1/articles, index action from ArticlesController is executed too.

因此,最好的方法是根据调用路由有条件地仅选择范围内的文章?

So, what is the best approach for conditionally selecting only the scoped articles depending on the calling route?

#if coming from the nested resource route
@articles = Articles.find_by_category_id(params[:category_id])
#else
@articles = Articles.all


推荐答案

在这里,您有两种选择,具体取决于您的逻辑和视图与范围的关系。
让我进一步解释。

You have two choices here, depending on how much your logic and your view is tied to the scope. Let me explain further.

第一个选择是确定控制器内的范围,如其他响应所解释的那样。我通常会设置一个@scope变量,以在模板中获得更多好处。

The first choice is to determine the scope within your controller, as already explained by the other responses. I usually set a @scope variable to get some additional benefits in my templates.

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 @ scope.my_named_scope.count ,而不是重复每个时间检查 params [:category_id]

The reason for the @scope variable is that you might need to know the scope of your request outside the single action. Let's assume you want to display the number of records in your view. You need to know whether you are filtering by category or not. In this case, you simply need to call @scope.count or @scope.my_named_scope.count instead of repeating each time the check on params[:category_id].

如果您的视图(带有类别的视图)可以很好地使用此方法和没有类别的那个非常相似。但是,如果按类别过滤的列表与没有类别的列表完全不同,会发生什么?这种情况经常发生:您的类别部分提供了一些针对类别的小部件,而您的文章部分则提供了与文章相关的小部件和过滤器。另外,Article控制器具有一些特殊的before_filters,您可能想使用它们,但是当文章列表属于某个类别时,则不必使用它们。

This approach works well if your views, the one with category and the one without category, are quite similar. But what happens when the listing filtered by category is completely different compared to the one without a category? This happens quite often: your category section provides some category-focused widgets while your article section some article-related widgets and filter. Also, your Article controller has some special before_filters you might want to use, but you don't have to use them when the article listing belongs to a category.

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 管理。

Now the listing filtered by category is managed by the CategoriesController and it inherits all the controller filters, layouts, settings... while the unfiltered listing is managed by the ArticlesController.

这通常是我最喜欢的选择,因为只需执行其他操作,您就不必通过大量的条件检查使视图和控制器变得混乱。

This is usually my favorite choice because with an additional action you don't have to clutter your views and controllers with tons of conditional checks.

这篇关于Rails:嵌套资源冲突,如何根据调用的路由来范围化索引操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆