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