问题
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/newas usual, but when usingmymodel_new_pathorlink_to @mymodelorform_for @my_modelor 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/newwhere the per-request string/portal/prefix/xyzzyis given by some method defined by us (and the partxyzzycan 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