Rails 4.1.2 - to_param转义斜杠(并打破应用程序)

时间:2014-07-30 08:12:16

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

我在我的应用to_param中使用来创建自定义网址(此自定义路径包含斜杠):

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只为show方法使用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

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

任何想法我该如何解决?

3 个答案:

答案 0 :(得分:1)

使用自动生成的网址助手时,我遇到了同样的问题。我使用调试器跟踪新行为的源(在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。我还没有找到一个好的例子&#34;对&#34;做到这一点的方法,但像这个简单的例子应该达到目的:

#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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

如何自己定义网址?

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 )