在 Rails 路由中抑制文件扩展名检测/格式映射

Suppress file extension detection / format mapping in Rails route

我有一个 Rails 形式的路由

get '/:collection/*files' => 'player#index'

其中 files 是一个以分号分隔的媒体文件列表,例如/my-collection/some-video.mp4%3Bsome-audio.mp3

这些由以下形式的控制器操作处理:

class PlayerController < ApplicationController
  def index
    @collection = params[:collection]
    @files = params[:files].split(';')
  end
end

并使用为每个文件显示 HTML5 <audio><video> 元素的模板呈现。

只要文件没有扩展名,这就可以正常工作,例如 /my-collection/file1%3Bfile2.

但是,如果我添加文件扩展名, /my-collection/foo.mp3%3Bbar.mp4, 我得到:

No route matches [GET] "/my-collection/foo.mp3%3Bbar.mp4"

如果我尝试使用单个文件,例如/my-collection/foo.mp3,我得到:

PlayerController#index is missing a template for this request format and variant. request.formats: ["audio/mpeg"] request.variant: []

基于this answer我在路由中添加了一个正则表达式约束:

  get '/:collection/*files' => 'player#index', constraints: {files: /[^\/]+/}

这解决了 没有路由匹配 的问题,但现在多个分离版本也失败了,缺少模板。 (无论如何这都不理想,因为我仍然宁愿在文件值中允许 /。但是 /.*/ 并没有更好地工作。)

我尝试了 format: false,使用和不使用 constraints,但仍然缺少模板

我还尝试了一个普通路径参数 (/:collection/:files),得到了与通配符 *files.

相同的行为

如何让 Rails 忽略并通过此路由的扩展?


注意: 我在 Ruby 2.5.1.

上使用 Rails 6.0.0

根据 this Rails issue 的讨论,神奇的公式似乎是将 defaults: {format: 'html'} 添加到 format: false

  get '/:collection/:files',
      to: 'player#index',
      format: false,
      defaults: {format: 'html'},
      constraints: {files: /.*/}