render default template when requested template is

2020-04-08 01:13发布

For a plugin I want to hack the following feature into Rails:

When a (partial) template does not exist (regardless of the format) I want to render a default template.

So say I call an action 'users/index' if users/index.html.erb does not (or other format) exist, 'default/index.html.erb' should be rendered.

Similarly, If I call an action 'locations/edit' and 'locations/edit.html.erb' does not exist, 'default/edit.html.erb' should be rendered

For partials, If I call an action 'locations/index' and the template 'locations/index.html.erb' calls the partial 'locations/_location' which does not exist, it should render 'default/_object'

The solution is seek gives me access to the templates variables (e.g. @users, @locations) and information on the requested path (e.g. users/index, locations/edit). And it should also work with partials.

I have thought of some options which I'll post below. None of them are completely satisfactory.

4条回答
Juvenile、少年°
2楼-- · 2020-04-08 01:42

I found a patch that is relatively clean, it only patches the lookup of the template which is exactly what was required in the question.


module ActionView
  class PathSet

    def find_template_with_exception_handling(original_template_path, format = nil, html_fallback = true)
      begin
        find_template_without_exception_handling(original_template_path, format, html_fallback)
      rescue ActionView::MissingTemplate => e
        # Do something with original_template_path, format, html_fallback
        raise e
      end
    end
    alias_method_chain :find_template, :exception_handling

  end
end
查看更多
▲ chillily
3楼-- · 2020-04-08 01:43

Solution 1:

Monkey patch ActionView::Base#render


module ActionView
  class Base
    def render_with_template_missing(*args, &block)
      # do something if template does not exist

      render_without_template_missing(*args, &block)
    end
    alias_method_chain :render, :template_missing
  end
end

This monkey patch requires to look into the (changing) internals of rails and results in ugly code, but probably works.

查看更多
虎瘦雄心在
4楼-- · 2020-04-08 01:55

Rails 3.1 automatically looks for files in application/template.html.erb after looking in controller/template.html.erb you can see this in the Exception like so:

Missing template [controller name]/index, application/index with {:locale=>[:en, :en], :formats=>[:html], :handlers=>[:erb, :coffee, :builder]}. Searched in: * "/path/to/rails_project/app/views" 

so, just put your default templates in app/views/application

查看更多
叼着烟拽天下
5楼-- · 2020-04-08 02:03

Solution 2:

Use 'rescue_from' in ApplicationController



class ApplicationController > ActionController::Base
  rescue_from ActionView::MissingTemplate do |exception|
    # use exception.path to extract the path information
    # This does not work for partials
  end
end



Drawback: does not work for partials.

查看更多
登录 后发表回答