5

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).

georgebrock
  • 28,393
  • 13
  • 77
  • 72
user1105595
  • 591
  • 2
  • 8
  • 20

2 Answers2

9

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)

georgebrock
  • 28,393
  • 13
  • 77
  • 72
  • Glad I could help, and welcome to Stack Overflow. If an answer solves your problem, you should mark it as accepted, more info on how and why here: http://meta.stackexchange.com/a/5235 – georgebrock Aug 31 '12 at 16:41
1

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.

georgebrock
  • 28,393
  • 13
  • 77
  • 72
jdoe
  • 15,665
  • 2
  • 46
  • 48