【问题标题】:Rails 4.1.2 - to_param escapes slashes (and breaks app)Rails 4.1.2 - to_param 转义斜杠(并破坏应用程序)
【发布时间】:2014-07-30 08:12:15
【问题描述】:

我在我的应用程序中使用to_param 创建自定义 URL(此自定义路径包含斜杠):

class Machine < ActiveRecord::Base
  def to_param
    MachinePrettyPath.show_path(self, cut_model_text: true)
  end
end

问题是,由于 Rails 4.1.2 的行为发生了变化,并且 Rails 不允许在 URL 中使用斜杠(当使用自定义 URL 时),所以它转义了斜杠。

我有这样的路线:

Rails.application.routes.draw do
  scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
      resources :machines, except: :destroy do
          collection do
            get  :search
            get  'search/:ad_type(/:machine_type(/:machine_subtype(/:brand)))', action: 'search', as: :pretty_search

            get  ':subcategory/:brand(/:model)/:id', action: 'show', as: :pretty
            patch ':subcategory/:brand(/:model)/:id', action: 'update'                                  # To be able to update machines with new rich paths.
          end
      end
  end
end

我尝试by recommendation in the thread 将 glob 参数仅用于 show 方法以确保它有效:

resources :machines, except: :destroy do
 #...
end

scope format: false do
 get '/machines/*id', to: "machines#show"
end

但这绝对行不通。我仍然有这些断开的链接:

http://localhost:3000/machines/tractor%2Fminitractor%2Fmodel1%2F405

当然,如果我自己替换转义斜线:

http://localhost:3000/machines/tractor/minitractor/model1/405

并尝试访问路径,然后页面将被打开。

有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4.1 actionpack


    【解决方案1】:

    我在使用自动生成的 url 帮助程序时遇到了同样的问题。我使用调试器跟踪新行为的源头(在 ActionDispatch::Journey::Visitors::Formatter 附近),但没有找到任何有希望的解决方案。看起来参数化模型现在被严格视为路径的单个斜杠分隔段并相应地转义,没有其他选项可以告诉格式化程序。

    据我所知,让 url helper 生成旧结果的唯一方法是使用原始路由文件并分别传递每个段,例如:

    pretty_machine_path(machine.subcategory, machine.brand, machine.model, machine.id)
    

    这太丑陋了,显然不是你想要一遍又一遍地做的事情。您可以向 MachinePrettyPath 添加一个方法,以将段生成为数组并为帮助程序分解结果(例如,pretty_machine_path(*MachinePrettyPath.show_path_segments(machine))),但这仍然非常冗长。

    在上述令人头疼的问题和您链接到的 Rails 票证中开发人员的“你做错了”态度之间,对我来说最简单的选择是硬着头皮写一个自定义 URL 帮助程序,而不是使用 to_param。我还没有找到一个很好的例子来说明这样做的“正确”方式,但是像这个简单的例子应该可以达到目的:

    #app/helpers/urls_helper.rb
    module UrlsHelper
      def machine_path(machine, options = {})
        pretty_machine_path(*MachinePrettyPath.show_path_segments(machine), options)
      end
    end
    
    #app/controllers/application_controller.rb
    class ApplicationController < ActionController::Base
      helper :urls #for the views
      include UrlsHelper #for controllers
      #...
    end
    

    【讨论】:

    【解决方案2】:

    如果你确定返回的 url 是安全的,你应该将 .html_safe 添加到返回的字符串中:

    MachinePrettyPath.show_path(self, cut_model_text: true).html_safe
    

    (没有看到其他可以转义的地方,但检查了您应用中的所有流程,可能是逐个方法手动测试)

    【讨论】:

    • 不,很遗憾,这个解决方案不起作用。在html_safe 之后,斜线仍然被转义。
    • 您应该检查 MachinePrettyPath.show_path(self, cut_model_text: true) 输出是否已经转义。如果是,您应该更深入地检查该函数
    【解决方案3】:

    自己定义网址怎么样?

    def to_param
      "#{ subcategory.title.parameterize }/#{ brand.name.parameterize }/#{ model.name.parameterize) }/#{ id }"
    end
    

    然后在你的路线中是这样的:

    get 'machines/*id', to: "machines#show"
    

    当您在模型上进行查找时,您还必须拆分参数 [:id]。

    Machine.find( params[:id].split("/").last ) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-23
      • 2011-03-15
      • 1970-01-01
      • 2018-10-16
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多