问题
Our Rails 4 application needs to be accessible over an archaic portal. This portal works by adding (from the perspective of the browser) a prefix to each URL; this prefix is removed by the portal before forwarding the request to my application.
So the browser calls https://portal.company.com/portal/prefix/xyzzy/myapp/mymodel/new
; the portal does its thing and requests https://myserver.company.com/myapp/mymodel/new
(passing along the stripped prefix in some irrelevant way). The prefix is dynamic and can change between requests.
The problem is that the portal is not able to rewrite the HTML pages served by my application. That is, it does not put in the prefix. It expects applications to either only emit relative URLs, or to add the portal prefix themselves.
So:
- A regular URL
/myapp/mymodel/new
, for example, must stay as is for when the application is accessed directly (for certain users which do not use the portal). - When accessed over the portal, our application must still understand
/myapp/mymodel/new
as usual, but when usingmymodel_new_path
orlink_to @mymodel
orform_for @my_model
or whatever other magic URL generators there are, it has to add the portal prefix. So, any URL emitted by the application must look like/portal/prefix/xyzzy/myapp/mymodel/new
where the per-request string/portal/prefix/xyzzy
is given by some method defined by us (and the partxyzzy
can change between requests).
How can I achieve that? My routes.rb
looks like this today:
MyApp::application.routes.draw do
scope ' /myapp' do
get ...
This probably has to stay as is, because URLs in incoming requests do not change when coming from the portal. But how do I influence the outgoing URLs?
回答1:
This suggestion will allow you to easily prefix the urls produced by the Rails path helpers as your require. Do note, however, it will also make these extended paths valid requests for your application - they shoud just route where expected but you'll get get some extra values in the params
hash that you can ignore, so I suspect this is possibly acceptable.
First, add all the prefix bits as optional parameters to your routes' base scope:
scope '(:portal/)(:prefixA/)(:prefixB)/myapp' do
# routes
end
Note that the those optional params cannot include the /
char without it being escaped by the path helpers, so if you have a few levels in the prefix (which it appears you do in the question) you'll need a few different params, all but the last followed by a slash, as above.
With that done, you should define default_url_options
in your ApplicationController
, it should return a hash of the values you need in your routes:
def default_url_options(_options={})
{
portal: 'portal',
prefixA: 'whatevertheprefixis',
prefixB: 'nextbitoftheprefix'
}
end
And that should do it, path helpers (along with link_to @object
etc) should all now include those values every time you use them.
Note that since the portal
bit at the start is also an optional parameter, you can simply add additional logic to default_url_options
and have it return an empty hash whenever you do not want this prefixing behaviour.
来源:https://stackoverflow.com/questions/41825182/add-a-prefix-to-generated-links-but-not-to-incoming-routes