By default, Rails can find views with the format, locale and template language in the filename (so I can create index.de.json.erb
)
Is it possible to add another, custom parameter to the view's filename?
I would like to pass the current subdomain, so http://foo.example.com/
would render index.foo.html.erb
, and http://bar.example.com/
would render index.bar.html.erb
(both of them with index.html.erb
fallback).
The resolving pattern that is used to look up views can only contain variables that are registered with the ActionView::LookupContext
class. The first step is therefore to register a new variable (subdomain
) with the LookupContext
class. You should do this in an initializer:
ActionView::LookupContext.register_detail(:subdomain) do
['default_subdomain']
end
Now the LookupContext
knows about the subdomain
, it can be included in the resolving pattern. For more detail about changing the resolving pattern, see the ActionView::FileSystemResolver
documentation, but essentially you should include the following, also in an initializer:
ActionController::Base.view_paths = ActionView::FileSystemResolver.new(
Rails.root.join('app', 'views'),
':prefix/:action{.:locale,}{.:subdomain,}{.:formats,}{.:handlers,}'
)
This pattern is eventually passed to Dir.glob
(after the :*
variables have been replaced). The glob pattern {.:subdomain,}
means “either .:subdomain
or nothing”, which provides the fallback to a view file with no subdomain if the file with a subdomain isn't found.
The final step is to update your ApplicationController
to pass the subdomain to the LookupContext
:
class ApplicationController < ActionController::Base
def details_for_lookup
{:subdomain => [request.subdomain]}
end
end
(This answer was mostly figured out by reading source code, some of these features aren't documented. It was tested with Rails 3.2.5)
I don't think you need a custom handler here. You don't perform some prepossessing of your templates, but you just need your templates to become domain-specific.
I would consider making something like this:
# in ApplicationController:
before_filter :set_view_paths
def set_view_paths
self.class.view_paths = Rails.root.join('app', 'views', controller_name, request.subdomain)
end
Then you have to put your templates for the foo
domain into foo
folders of each views/controller_name
path.
Also check append/prepend_view_path
documentation to allow defaults in case of absence of a domain view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With