Rails路由 - 如何使它们不区分大小写?

12

Ruby on Rails中的路由是区分大小写的。似乎有人之前提出过这个问题,并被标记为将不予修复。

http://rails.lighthouseapp.com/projects/8994/tickets/393-routes-are-case-sensitive

我认为这很不幸,因为我在自己的应用程序中并没有看到路由对大小写敏感的任何好处,而对于缺点来说,它会造成混淆的潜力,从我的角度来看,也会显得缺乏技术含量。

那么,如何使我的路由不区分大小写呢?

我在谷歌搜索中找到了这个提示:

map.connect "web_feeds/:action", :controller  => 'web_feeds', :action => /[a-z_]+/i

这很聪明,但它仍然使url中的web_feeds部分区分大小写。 我没有看到任何类似的方法来解决这个问题,不过如果要手动输入每个可能的wEb_feEds组合,那显然是一个可怕的解决方案,无论出于任何原因。

7个回答

12

在Rails中,路由是区分大小写的,因为URL也是区分大小写的。根据W3C的说法:

URL总体上是区分大小写的(除了机器名称)。有些URL或URL的一些部分可能不区分大小写,但识别它们并不容易。用户应该始终考虑URL是区分大小写的。


有趣,我不知道。 - Davy8
我认为,如果Web是从Windows开始的话,它可能不会变成现在这个样子! - John Topley
24
我理解有时区分大小写很重要(尽管我只能想到一些特殊情况),但对于普通用途来说,这与用户期望相违背。用户期望stackoverflow.com/questions和stackoverflow.com/Questions是相同的,实际上也确实如此。而且我不确定普通用户是否会考虑W3C的建议,“应始终将URL视为区分大小写的”。 - William Jones
1
我认为应该对人类输入的内容宽容一些,但是要将其301重定向到URL的规范版本。 - Lyle
@lyle,使用route_downcaser gem,你可以选择进行重定向。 - Carsten Gehling

7

以上解决方案不适用于Rails 3,但我现在已经修复了。 - Carsten Gehling
1
我终于把它做成了一个宝石,所以使用起来更加容易:https://rubygems.org/gems/route_downcaser - Carsten Gehling
如果您的某些资产/图像名称为混合大小写,则此解决方案存在问题。 例如,如果您已经在使用来自assets/images/ABc_xyZZ.png(混合大小写)的图像,则在使用此解决方案后,它将尝试定位assets/images/abc_xyzz.png(小写),服务器将响应404未找到。 - Nadeem Yasin
@NadeemYasin 这可以通过使用排除初始化器来解决。# config/initializers/route_downcaser.rbRouteDowncaser配置 do |config| config.redirect = true config.exclude_patterns = [ /assets//i, /fonts//i, /some/important/path/i ] end - MicFin

4

你可以尝试另一种方法。在服务器端进行大小写转换,并将所有内容发送到Rails小写处理。

我认为你可以通过mod_rewrite或mod_spelling实现这一点。


3
一种简单的解决方案可能不够优雅,但仍然可行: 在您的应用程序控制器中使用 before_filter,如下所示。
  before_filter :validate_case

  def validate_case
    if request.url != request.url.downcase
      redirect_301_permanent_to request.url.downcase
    end
  end

  def redirect_301_permanent_to(url)
     redirect_to url, :status=>:moved_permanently 
  end

如我所说,这并不是一种优雅但可行的方法,所以请勿投反对票。:P


最好在Rack中完成。在应用控制器中,您已经通过Rails的路由分发器传递了。 - Carsten Gehling

2
只需将其默认转换为小写即可进行猴子补丁。简单示例:
module ActionController
  module Caching
    module Pages
      def cache_page(content = nil, options = nil)
        return unless perform_caching && caching_allowed

        path = case options
          when Hash
            url_for(options.merge(:only_path => true, :skip_relative_url_root => true, :format => params[:format]))
          when String
            options
          else
            request.path
        end

        path = path.downcase

        self.class.cache_page(content || response.body, path)
      end
    end
  end
end

正如W3C所述,URL是区分大小写的。 - Neil Middleton

0
(几年后发布此帖)
如果您只想让特定路由不区分大小写,就像在我的情况下一样,我最终所做的是以下内容。
假设您的路由为:
  get "items/:id" => "item#show"

这将解析/item/123,但不会解析/ITEM/123Item/123

您可以使用段约束,将item视为参数,并添加默认值,以便您的路由助手不需要指定它(因此保持与上面原始路由相同):

  get ":item/:id", constraints: { item: /item/i }, defaults: { item: "item" }  => "item#show"

如果您在/item下有多个路由,您可以使用作用域来概括这个概念:

scope ":item/", constraints: { item: /item/i }, defaults: { item: "item" } do
  get "/:id" => "item#show"
  delete "/:id" => "item#destroy"
end

0

虽然URL是区分大小写的,但如果您想使路由不区分大小写,有一个不太正规的方法可以实现。

在application_controller.rb中添加以下内容:

rescue_from ActionController::RoutingError do |exception|
 redirect_to request.url.downcase
end

但实际上不要这样做。对于任何不存在的路由,您会创建一个重定向循环。您真的应该解析request.request_uri成其组件,将它们转换为小写,并使用它们生成合法的路由进行重定向。正如我一开始提到的那样,这是一个肮脏的hack。然而,我认为这比让您的路由映射变得丑陋和hackish要好。


3
你应该检查它是否已经小写,类似于: 如果请求的URL不等于请求的URL小写, 则重定向到请求的URL小写。 否则,

显示404文件。

- vise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接