Module: ActivityNotification::Renderable
- Included in:
- ORM::ActiveRecord::Notification, ORM::Dynamoid::Notification, ORM::Mongoid::Notification
- Defined in:
- lib/activity_notification/renderable.rb
Overview
Provides logic for rendering notifications. Handles both i18n strings support and smart partials rendering (different templates per the notification key). This module deeply uses PublicActivity gem as reference.
Instance Method Summary collapse
-
#layout_path(path = nil, root = nil) ⇒ String
Returns layout path from options.
-
#partial_path(path = nil, root = nil, target = nil) ⇒ String
Returns partial path from options.
-
#prepare_assigns(params) ⇒ Hash
Returns assigns parameter for view.
-
#prepare_locals(params) ⇒ Hash
Returns locals parameter for view There are three variables to be add by method: * notification * controller * parameters [converted into a HashWithIndifferentAccess].
-
#prepare_parameters(params) ⇒ Hash
Prepares parameters with @prepared_params.
-
#render(context, params = {}) ⇒ String
Renders notification from views.
-
#text(params = {}) ⇒ String
Virtual attribute returning text description of the notification using the notification’s key to translate using i18n.
Instance Method Details
#layout_path(path = nil, root = nil) ⇒ String
Returns layout path from options
196 197 198 199 200 |
# File 'lib/activity_notification/renderable.rb', line 196 def layout_path(path = nil, root = nil) path.nil? and return root ||= 'layouts' select_path(path, root) end |
#partial_path(path = nil, root = nil, target = nil) ⇒ String
Returns partial path from options
178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/activity_notification/renderable.rb', line 178 def partial_path(path = nil, root = nil, target = nil) controller = ActivityNotification.get_controller if ActivityNotification.respond_to?(:get_controller) root ||= "activity_notification/notifications/#{target}" if target.present? root ||= controller.target_view_path if controller.present? && controller.respond_to?(:target_view_path) root ||= 'activity_notification/notifications/default' template_key = notifiable.respond_to?(:overriding_notification_template_key) && notifiable.overriding_notification_template_key(@target, key).present? ? notifiable.overriding_notification_template_key(@target, key) : key path ||= template_key.tr('.', '/') select_path(path, root) end |
#prepare_assigns(params) ⇒ Hash
Returns assigns parameter for view
206 207 208 |
# File 'lib/activity_notification/renderable.rb', line 206 def prepare_assigns(params) params.delete(:assigns) || {} end |
#prepare_locals(params) ⇒ Hash
Returns locals parameter for view There are three variables to be add by method:
-
notification
-
controller
-
parameters [converted into a HashWithIndifferentAccess]
218 219 220 221 222 223 224 225 |
# File 'lib/activity_notification/renderable.rb', line 218 def prepare_locals(params) locals = params.delete(:locals) || {} prepared_parameters = prepare_parameters(params) locals.merge\ notification: self, controller: ActivityNotification.get_controller, parameters: prepared_parameters end |
#prepare_parameters(params) ⇒ Hash
Prepares parameters with @prepared_params. Converted into a HashWithIndifferentAccess.
232 233 234 |
# File 'lib/activity_notification/renderable.rb', line 232 def prepare_parameters(params) @prepared_params ||= ActivityNotification.cast_to_indifferent_hash(parameters).merge(params) end |
#render(context, params = {}) ⇒ String
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>
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/activity_notification/renderable.rb', line 150 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)) assigns = prepare_assigns(params) locals = prepare_locals(params) begin context.render params.merge(partial: partial, layout: layout, assigns: assigns, 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, assigns: assigns, locals: locals) else raise e end end end |
#text(params = {}) ⇒ String
Virtual attribute returning text description of the notification using the notification’s key to translate using i18n.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/activity_notification/renderable.rb', line 13 def text(params = {}) k = key.split('.') k.unshift('notification') if k.first != 'notification' if params.has_key?(:target) k.insert(1, params[:target]) else k.insert(1, target.to_resource_name) end k.push('text') k = k.join('.') attrs = (parameters.symbolize_keys.merge(params) || {}).merge( group_member_count: group_member_count, group_notification_count: group_notification_count, group_member_notifier_count: group_member_notifier_count, group_notifier_count: group_notifier_count ) # Generate the :default fallback key without using pluralization key :count default = I18n.t(k, **attrs) I18n.t(k, **attrs.merge(count: group_notification_count, default: default)) end |