def render(context, params = {})
      params[:i18n] and return context.render plain: self.text(params)

      partial = partial_path(*params.values_at(:partial, :partial_root, :target))
      layout  = layout_path(*params.values_at(:layout, :layout_root))
      locals  = prepare_locals(params)

      begin
        context.render params.merge(partial: partial, layout: layout, locals: locals)
      rescue ActionView::MissingTemplate => e
        if params[:fallback] == :text
          context.render plain: self.text(params)
        elsif params[:fallback].present?
          partial = partial_path(*params.values_at(:fallback, :partial_root, :target))
          context.render params.merge(partial: partial, layout: layout, locals: locals)
        else
          raise e
        end
      end
    end
def render(context, params = {})
      params[:i18n] and return context.render plain: self.text(params)

      partial = partial_path(*params.values_at(:partial, :partial_root, :target))
      layout  = layout_path(*params.values_at(:layout, :layout_root))
      locals  = prepare_locals(params)

      begin
        context.render params.merge(partial: partial, layout: layout, locals: locals)
      rescue ActionView::MissingTemplate => e
        if params[:fallback] == :text
          context.render plain: self.text(params)
        elsif params[:fallback].present?
          partial = partial_path(*params.values_at(:fallback, :partial_root, :target))
          context.render params.merge(partial: partial, layout: layout, locals: locals)
        else
          raise e
        end
      end
    end
Renders notification from views.

 The preferred way of rendering notifications is
 to provide a template specifying how the rendering should be happening.
 However, you can choose using _i18n_ based approach when developing
 an application that supports plenty of languages.

 If partial view exists that matches the "target" type and "key" attribute
 renders that partial with local variables set to contain both
 Notification and notification_parameters (hash with indifferent access).

 If the partial view does not exist and you wish to fallback to rendering
 through the i18n translation, you can do so by passing in a :fallback
 parameter whose value equals :text.

 If you do not want to define a partial view, and instead want to have
 all missing views fallback to a default, you can define the :fallback
 value equal to the partial you wish to use when the partial defined
 by the notification key does not exist.

 Render a list of all notifications of @target from a view (erb):
   <ul>
     <% @target.notifications.each do |notification|  %>
       <li><%= render_notification notification %></li>
     <% end %>
   </ul>

 Fallback to the i18n text translation if the view is missing:
   <ul>
     <% @target.notifications.each do |notification|  %>
       <li><%= render_notification notification, fallback: :text %></li>
     <% end %>
   </ul>

 Fallback to a default view if the view for the current notification key is missing:
   <ul>
     <% @target.notifications.each do |notification|  %>
       <li><%= render_notification notification, fallback: 'default' %></li>
     <% end %>
   </ul>

 = Layouts

 You can supply a layout that will be used for notification partials
 with :layout param.
 Keep in mind that layouts for partials are also partials.

 Supply a layout:
   # in views:
   # All examples look for a layout in app/views/layouts/_notification.erb
   render_notification @notification, layout: "notification"
   render_notification @notification, layout: "layouts/notification"
   render_notification @notification, layout: :notification

   # app/views/layouts/_notification.erb
   <p><%= notification.created_at %></p>
   <%= yield %>

 == Custom Layout Location

 You can customize the layout directory by supplying :layout_root
 or by using an absolute path.

 Declare custom layout location:
   # Both examples look for a layout in "app/views/custom/_layout.erb"
   render_notification @notification, layout_root: "custom"
   render_notification @notification, layout: "/custom/layout"

 = Creating a template

 To use templates for formatting how the notification should render,
 create a template based on target type and notification key, for example:

 Given a target type users and key _notification.article.create_, create directory tree
 _app/views/activity_notification/notifications/users/article/_ and create the _create_ partial there

 Note that if a key consists of more than three parts splitted by commas, your
 directory structure will have to be deeper, for example:
   notification.article.comment.reply => app/views/activity_notification/notifications/users/article/comment/_reply.html.erb

 == Custom Directory

 You can override the default `activity_notification/notifications/#{target}` template root with the :partial_root parameter.

 Custom template root:
    # look for templates inside of /app/views/custom instead of /app/views/public_directory/activity_notification/notifications/#{target}
    render_notification @notification, partial_root: "custom"

 == Variables in templates

 From within a template there are three variables at your disposal:
 * notification
 * controller
 * parameters [converted into a HashWithIndifferentAccess]

 Template for key: _notification.article.create_ (erb):
   <p>
     Article <strong><%= parameters[:title] %></strong>
     was posted by <em><%= parameters["author"] %></em>
     <%= distance_of_time_in_words_to_now(notification.created_at) %>
   </p>

 @param [ActionView::Base] context
 @param [Hash] params Parameters for rendering notifications
 @option params [String, Symbol] :target       (nil)                     Target type name to find template or i18n text
 @option params [String]         :partial_root ("activity_notification/notifications/#{target}", controller.target_view_path, 'activity_notification/notifications/default') Partial template name
 @option params [String]         :partial      (self.key.tr('.', '/'))   Root path of partial template
 @option params [String]         :layout       (nil)                     Layout template name
 @option params [String]         :layout_root  ('layouts')               Root path of layout template
 @option params [String, Symbol] :fallback     (nil)                     Fallback template to use when MissingTemplate is raised. Set :text to use i18n text as fallback.
 @option params [Hash]           others                                  Parameters to be set as locals
 @return [String] Rendered view or text as string