Its not May anymore, but maybe this belongs in A May of WTFs. I’m trying to figure out how to get the router to let me define resourceful routes that allow a wildcard glob. Something like Github’s: /:org/*path_to_file
, but with the additional wrinkle of another segment on the end of that (like shares? I dunno, its a contrived example).
I can pass the constraint to the resources
block, but the url helper tries to escape the param:
resources :files, param: :path, constraints: { path: /.+?/ }, only: [:index, :show] do
resources :shares, only: [:index, :show]
end
#
# Paths & prefixes look right
#
# account_file_shares GET /:account_slug/files/:file_path/shares(.:format) shares#index
# account_file_share GET /:account_slug/files/:file_path/shares/:id(.:format) shares#show
# account_files GET /:account_slug/files(.:format) files#index
# account_file GET /:account_slug/files/:path(.:format) files#show
#
# But globbing gets escaped in the url helper
#
# [Development]>> app.account_file_path("test", "some/path")
# => "/test/files/some%2Fpath"
I can write out the scope
/match
by hand to mimic it, but it behaves differently.
scope "/files", controller: :files do
get "/" => :index, as: :files
scope "*path" do
get "/" => :show, as: :file
scope "/shares", controller: :shares do
get :index, as: :file_shares
get "/:id" => :show, as: :file_share
end
end
end
#
# WTF happened to the account scope, why is it at the end now?
#
# account_files GET /files/:account_slug(.:format) files#index
# account_file GET /files/*path/:account_slug(.:format) files#show
# account_file_shares GET /files/*path/shares/:account_slug/index(.:format) shares#index
# account_file_share GET /files/*path/shares/:account_slug/:id(.:format) shares#show
Finally, I can mix and match, but there’s still some subtle differences, but at least the route helper works:
resources :files, param: :path, only: [:index, :show] do
collection do
scope "/*path" do
get :show, as: :file
resources :shares, only: [:index, :show]
end
end
end
#
# Show route prefix has a different naming scheme.
# => Expected "account_file", got "file_account_files".
#
# Middle part of of the nested route prefix got dropped.
# => Expected "account_file_shares", got "account_shares".
#
# file_account_files GET /:account_slug/files/*path(.:format) files#show
# account_shares GET /:account_slug/files/*path/shares(.:format) shares#index
# account_share GET /:account_slug/files/*path/shares/:id(.:format) shares#show
# account_files GET /:account_slug/files(.:format) files#index
# account_file GET /:account_slug/files/:path(.:format) files#show
#
# At least the url helper works:
#
# [Development]>> app.file_account_files_path("test", "some/path")
# => "/test/files/some/path"
I’ve dug into actionpack/routes/mapper.rb
so I can write my own resourceful-like routes to allow the wildcard param, but it uses a bunch of internal helpers (eg with_scope_level(:resources)
and resource_scope
) that I technically have access to, but I spent and afternoon trying to figure out how I can use them myself, and wasn’t able to make anything work. My custom one would probably just break on the next point release of Rails, anyways.
Is there a clean(er) way to leverage wildcard globs in resourceful routes that maintain the naming scheme of the url helpers?