Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom variable in Rails view filename

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

like image 709
user1105595 Avatar asked Aug 30 '12 19:08

user1105595


2 Answers

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)

like image 95
georgebrock Avatar answered Oct 16 '22 00:10

georgebrock


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.

like image 1
jdoe Avatar answered Oct 16 '22 01:10

jdoe