Reputation: 51123
I have a Rails route of the form
get '/:collection/*files' => 'player#index'
where files
is intended to be a semicolon-separated list of media files, e.g. /my-collection/some-video.mp4%3Bsome-audio.mp3
These are handled by a controller action of the form:
class PlayerController < ApplicationController
def index
@collection = params[:collection]
@files = params[:files].split(';')
end
end
and rendered with a template that displays an HTML5 <audio>
or <video>
element for each file.
This works fine so long as the files have no extension, e.g.
/my-collection/file1%3Bfile2
.
However, if I add the file extensions,
/my-collection/foo.mp3%3Bbar.mp4
,
I get:
No route matches [GET] "/my-collection/foo.mp3%3Bbar.mp4"
And if I try it with a single file, e.g. /my-collection/foo.mp3
, I get:
PlayerController#index is missing a template for this request format and variant. request.formats: ["audio/mpeg"] request.variant: []
Based on this answer I added a regex constraint to the route:
get '/:collection/*files' => 'player#index', constraints: {files: /[^\/]+/}
This solves the No route matches problem, but now the multiple, separated version also fails with missing a template. (It's not ideal anyway, since I'd still rather allow /
in file values. But /.*/
didn't work any better.)
I tried format: false
, with and without constraints
, and still got missing a template.
I also tried an ordinary path parameter (/:collection/:files
), and got the same behavior as for the wildcard *files
.
How can I get Rails to ignore and pass through the extension for this route?
Note: I'm using Rails 6.0.0 on Ruby 2.5.1.
Upvotes: 3
Views: 1159
Reputation: 51123
Following the discussion on this Rails issue, the magic formula appears to be adding defaults: {format: 'html'}
to format: false
:
get '/:collection/:files',
to: 'player#index',
format: false,
defaults: {format: 'html'},
constraints: {files: /.*/}
Upvotes: 6