Skip to content

Instantly share code, notes, and snippets.

@ihsaneddin
Last active February 26, 2016 07:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ihsaneddin/21a23134c94d44fbef06 to your computer and use it in GitHub Desktop.
Save ihsaneddin/21a23134c94d44fbef06 to your computer and use it in GitHub Desktop.
en:
notifications:
post:
after_update:
subject:
default: "%{sender} has updated his post"
notifiable_attributes:
state:
published: "%{sender} has published his post"
module Notifications
module Notifiable
extend ActiveSupport::Concern
included do
include Rails.application.routes.url_helpers
end
module ClassMethods
def can_be_notified options = {}
default_options = {sender_notification: nil, recipients_notification: nil, notification_yaml_text: nil, notifiable_attributes: [], notification_on: [:after_create, :around_update]}
options = default_options.merge options
if options[:recipients_notification].is_a?(Array) or options[:recipients_notification].is_a?(Symbol)
options.each do |key, val|
self.class_attribute key
self.send("#{key}=", val)
end
set_notification_relation
set_notification_callbacks options
end
end
protected
def set_notification_relation
has_many :notifications, as: :notifiable, dependent: :destroy, class_name: 'Notification'
end
def set_notification_callbacks options ={}
if options[:notification_on] and ( options[:notification_on].is_a?(Array) or options[:notification_on].is_a?(Symbol))
options[:notification_on].respond_to?(:each) ? options[:notification_on].each {|call| send(call, :create_notification)} : send(options[:notification_on], :create_notification)
end
end
end
def create_notification
if notification_sender.present? and notification_text.present?
notification_params = { subject: notification_text, sender: notification_sender }
new_notification= self.notifications.new notification_params
new_notification.receipts << notification_recipients
new_notification.save
end
yield if block_given?
end
def notification_recipients
get_recipients_notification
end
def get_recipients_notification methods = []
methods= self.class.recipients_notification if methods.blank?
recipient_brad=nil
recipient_brad= methods.kind_of?(Array) ? recipients_notification.each{|r| recipient_brad= recipient_brad.nil?? self.send(r) : recipient_brad.send(r) } : self.send(methods)
recipient_brad
end
def notification_sender
get_sender_notification
end
def get_sender_notification methods = []
methods= self.class.sender_notification if methods.blank?
get_recipients_notification methods
end
def notification_text
@notification_text ||= get_notification_text
end
def get_notification_text
if self.class.notification_yaml_text.nil?
notif_text_key = "notifications.#{self.class.name.demodulize.downcase}.#{callback_state}"
default_title = ["#{notif_text_key}.subject.default"]
if self.notifiable_attributes.present? and callback_state.eql?(:after_update)
title = []
current_notifiable_attributes = self.notifiable_attributes.dup
notifiable_attributes_with_values = notifiable_attributes.last.is_a?(Hash) ? current_notifiable_attributes.pop : {}
current_notifiable_attributes.each do |att|
if self.send("#{att}_changed?")
title << "#{notif_text_key}.subject.notifiable_attributes.#{att}"
end
end
notifiable_attributes_with_values.each do |att, val|
if send("#{att}_changed?")
current_att_val= self.send("#{att}")
if val.is_a? Array
if val.include? current_att_val
title << "#{notif_text_key}.subject.notifiable_attributes.#{att}.#{current_att_val}"
end
end
end
end
default_title= title
end
default_title= default_title.map{|nt| I18n.t(nt, sender: notification_sender.try(:display_name)) }.join(' and ')
else
default_title= send self.class.notification_yaml_text
end
default_title
end
def callback_state
id_changed?? :after_create : :after_update
end
end
end
# == schema Information
#
#table name: notifications
#id
#notifiable_id :integer
#notifiable_type :string
#sender_id :integer
#body :text
#send_email :boolean
#created_at
#updted_at
class Notification < ActiveRecord::Base
include Notifications::NotificationMethods
end
class NotificationReceipt < ActiveRecord::Base
belongs_to :user
belongs_to :notification
end
module Notifications
module NotificationMethods
extend ActiveSupport::Concern
included do
extend Finders
scope :in_order, -> { order('created_at ASC') }
scope :recent, -> { order("created_at DESC") }
scope :unread, -> { recent.where(read: false) }
belongs_to :notifiable, polymorphic: true
belongs_to :sender, class_name: 'User', foreign_key: :sender_id
has_many :receipts, class_name: 'NotificationReceipt', foreign_key: :notification_id
has_many :users, through: :receipts
end
module Finders
def find_notifications_for recipient
joins(:receipts).where(["notification_receipts.user_id = ?", recipient.id]).order("notifications.created_at DESC")
end
def find_unread_notifications_for recipient
find_notifications_for(recipient).where(["notification_receipts.read = ?", false])
end
def find_notifications_send_by sender
where(["sender_id = ?", sender.id]).order("created_at DESC")
end
def find_notifications_for_notifiable notifiable_type, notifiable_id
recent.where(["notifiable_type = ? and notifiable_id = ?", notifiable_type, notifiable_id])
end
end
def notification_receipt_for(user)
receipts.order("created_at").find_by_user_id(user.id)
end
end
end
module Notifications
module Notify
extend ActiveSupport::Concern
included do
has_many :notifications, foreign_key: :sender_id
has_many :notification_receipts
has_many :notifications, through: :notification_receipts
end
end
end
class < Post
include Notifications::Notifiable
can_be_notified sender_notification: :user, recipients_notification: :who_receive_notification, notifiable_attributes: [state: ['published']], notification_on: :around_update
belongs_to :user
private
def recipients_notifications
[User.last.notification_receipts.new(route: post_path(self)) ]
end
end
#schema Information
#id
#email
#username
class User < ActiveRecord::Base
include Notifications::Notify
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment