Rails 4.1.2 – to_param转义斜杠(并打破app)

我在我的应用程序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 

我尝试在线程中推荐使用glob param只是为了确保它的工作方式:

 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 

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

任何想法如何解决这个问题?

使用自动生成的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 

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

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

(没有看到任何其他地方可以逃脱,但检查你的应用程序中的所有流程,也许通过方法手动测试方法)

如何自己定义url?

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

然后在你的路线中这样的事情:

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

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

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