简体   繁体   English

将多个动作路由到同一个 controller 和动作

[英]Routing more than one action to the same controller and action

I am trying to get something like this working on my Rails app:我正在尝试在我的 Rails 应用程序上使用类似的东西:

match '/:language', :to => 'posts#search_result'
match '/:tag', :to => 'posts#search_result'
match '/:language/:tag', :to => 'posts#search_result'

I am using this search_result action to filter some posts depending of the language and the tag.我正在使用这个 search_result 操作来根据语言和标签过滤一些帖子。

The problem is that sometimes:tag will be nil or:language will be nil;问题是有时:tag 为 nil 或:language 为 nil; so i have these 3 possibilities when calling the action:所以我在调用动作时有这 3 种可能性:

<%=link_to "Spanish", {:controller => 'posts', :action => 'search_result', :language => "spanish"} %>

<%= link_to "Spanish", {:controller => 'posts', :action => 'search_result', :language => "spanish", :tag => @tag} %>

<%=link_to "#{tag.name}", {:controller => 'posts', :action => 'search_result', :tag => @tag} %>

And I am expection to have URLs like:我希望有这样的 URL:

/spanish          (for the first case)
/spanish/rails    (where rails is a tag, for the second case)
/rails            (for the third case)

But right now i am getting the rigth thing for the first and third case, but for the second case i am getting: /spanish?tag=rails or again /spanish (depending on if i had selected a tag first or a language first).但是现在我在第一种和第三种情况下得到了正确的东西,但对于第二种情况,我得到: /spanish?tag=rails或再次/spanish (取决于我是先选择标签还是先选择语言) .

I hope i explained myself right.我希望我对自己的解释是正确的。 Any idea??.任何想法??。 thanks..谢谢..

Instead of defining /:language and /:language/:tag separately, define them together, with /:tag as an optional URI element.不要单独定义 /:language 和 /:language/:tag ,而是将它们一起定义,将 /:tag 作为可选的 URI 元素。

match '/:language(/:tag)', :to => 'posts#search_result'

I believe routes are matched (and URIs generated from them) in the order that the routes are defined.我相信路由是按照定义路由的顺序匹配的(以及从它们生成的 URI)。 You defined /:lang before you defined /:lang/:tag, so it matched /:lang and made:tag a GET parameter.您在定义 /:lang/:tag 之前定义了 /:lang,因此它匹配 /:lang 并制作了:tag GET 参数。 I suppose you could optimize the ordering of your definitions, but I believe using the above syntax is the preferred method.我想您可以优化定义的顺序,但我相信使用上述语法是首选方法。

The router cannot tell the difference between a:language and a:tag.路由器无法区分 a:language 和 a:tag 之间的区别。

Just because your routes say "language" and "tag" when you are constructing your code in the view.. remember that in the html this has been translated into just plain ole URLs eg /spanish or /rails只是因为当您在视图中构建代码时,您的路线会说“语言”和“标签”。请记住,在 html 中,这已被翻译成普通的 ole URL,例如 /spanish 或 /rails

the route then has to be figured out from this URL.然后必须从这个 URL 中找出路线。

Now as I said, the router can't tell that a particular word is a language or a tag... and the plain-ole-URL doesn't have the word "tag" or "language" in it anymore... so your two routes here:现在,正如我所说,路由器无法分辨特定单词语言还是标签……而普通 ole-URL 中不再包含单词“标签”或“语言”……所以你的两条路线:

match '/:language', :to => 'posts#search_result'
match '/:tag', :to => 'posts#search_result'

are both the same kind of URL都是一种 URL

Just a single token after the slash.斜线后只有一个标记。 Here are some examples that will match that route:以下是一些与该路线匹配的示例:

/greek
/spanish
/rails
/urdu
/whatever

They will all match the first route that matches on "a single token after a slash"... which means your router will match all of them to the "language" route and will never ever match the "/:tag" route, because it's already matched on the route above.它们将匹配匹配“斜线后的单个令牌”的第一个路由......这意味着您的路由器会将它们全部匹配到“语言”路由并且永远不会匹配“/:标签”路由,因为它已经在上面的路线上匹配了。

he he: it's all greek to the router;)呵呵:对路由器来说都是希腊语;)

Edit:编辑:

Hi, this is helping me a lot to understand how routing works.. but still i can't see it clear.嗨,这对我了解路由的工作原理很有帮助。但我仍然看不清楚。 I understand what you said, and so basically i understand i should do something like match '/tags/:tag to at least only route to posts#search_result the URLS starting by /tag.. what would be a solution??我明白你所说的,所以基本上我明白我应该做一些类似 match '/tags/:tag 的事情,以至少只路由到以 /tag 开头的 URLs#search_result 。什么是解决方案?

yes, "/tags/:tag" would be clear and unambiguous, but if you want it to truly flexible in tag vs language you would be better served by the simple:是的,“/tags/:tag”将是清晰明确的,但是如果您希望它在标签与语言方面真正灵活,那么简单的方法会更好:

match '/posts/search', :to => 'posts#search_result'

which can use any of your link_to examples above to generate eg:它可以使用上面的任何 link_to 示例来生成,例如:

/posts/search?tag=rails
/posts/search?language=spanish
/posts/search?language=spanish&tag=rails

It's also far more clear what is being passed and why .它也更清楚正在传递什么以及为什么

The description of the third URL is "I'm searching for a set of posts which have language = spanish and tag = rails"第三个 URL 的描述是“我正在寻找一组语言 = 西班牙语和标签 = 导轨的帖子”

Your URL should reflect the resource (which in this case is a set of posts) everything else is better done as query params.您的 URL 应该反映资源(在这种情况下是一组帖子),其他一切都最好作为查询参数完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM