Skip to content

Commit

Permalink
Add has_noticed_notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
excid3 committed Jan 29, 2024
1 parent 55b60c2 commit d2cb17a
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/noticed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def self.deprecator # :nodoc:
autoload :BulkDeliveryMethod, "noticed/bulk_delivery_method"
autoload :Coder, "noticed/coder"
autoload :DeliveryMethod, "noticed/delivery_method"
autoload :HasNotifications, "noticed/has_notifications"
autoload :RequiredOptions, "noticed/required_options"
autoload :Translation, "noticed/translation"

Expand Down
6 changes: 6 additions & 0 deletions lib/noticed/engine.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module Noticed
class Engine < ::Rails::Engine
isolate_namespace Noticed

initializer "noticed.has_notifications" do
ActiveSupport.on_load(:active_record) do
include Noticed::HasNotifications
end
end
end
end
49 changes: 49 additions & 0 deletions lib/noticed/has_notifications.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Noticed
module HasNotifications
# Defines a method for the association and a before_destroy callback to remove notifications
# where this record is a param
#
# class User < ApplicationRecord
# has_noticed_notifications
# has_noticed_notifications param_name: :owner, destroy: false, model: "Notification"
# end
#
# @user.notifications_as_user
# @user.notifications_as_owner

extend ActiveSupport::Concern

class_methods do
def has_noticed_notifications(param_name: model_name.singular, **options)
define_method :"notifications_as_#{param_name}" do
model = options.fetch(:model_name, "Noticed::Event").constantize
case current_adapter
when "postgresql", "postgis"
model.where("params @> ?", Noticed::Coder.dump(param_name.to_sym => self).to_json)
when "mysql2"
model.where("JSON_CONTAINS(params, ?)", Noticed::Coder.dump(param_name.to_sym => self).to_json)
when "sqlite3"
model.where("json_extract(params, ?) = ?", "$.#{param_name}", Noticed::Coder.dump(self).to_json)
else
# This will perform an exact match which isn't ideal
model.where(params: {param_name.to_sym => self})
end
end

if options.fetch(:destroy, true)
before_destroy do
send(:"notifications_as_#{param_name}").destroy_all
end
end
end
end

def current_adapter
if ActiveRecord::Base.respond_to?(:connection_db_config)
ActiveRecord::Base.connection_db_config.adapter
else
ActiveRecord::Base.connection_config[:adapter]
end
end
end
end
4 changes: 4 additions & 0 deletions test/dummy/app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
class User < ApplicationRecord
has_many :notifications, as: :recipient, dependent: :destroy, class_name: "Noticed::Notification"

# Used for querying Noticed::Event where params[:user] is a User instance
has_noticed_notifications
has_noticed_notifications param_name: :owner, destroy: false
end
11 changes: 11 additions & 0 deletions test/fixtures/noticed/events.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,14 @@ three:
params:
foo: bar
notifications_count: 2

account:
type: ReceiptNotifier
record: two
record_type: User
params:
foo: bar
account:
_aj_globalid: gid://dummy/Account/<%= ActiveRecord::FixtureSet.identify(:primary) %>
_aj_symbol_keys:
- account
47 changes: 47 additions & 0 deletions test/has_notifications_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require "test_helper"

class HasNotificationsTest < ActiveSupport::TestCase
test "has_noticed_notifications" do
assert User.respond_to?(:has_noticed_notifications)
end

test "noticed notifications association" do
assert user.respond_to?(:notifications_as_user)
end

test "noticed notifications with custom name" do
assert user.respond_to?(:notifications_as_owner)
end

test "association returns notifications" do
assert_difference "user.notifications_as_user.count" do
SimpleNotifier.with(user: user, message: "test").deliver(user)
end
end

test "association with custom name returns notifications" do
assert_difference "user.notifications_as_owner.count" do
SimpleNotifier.with(owner: user, message: "test").deliver(user)
end
end

test "deletes notifications with matching param" do
SimpleNotifier.with(user: user, message: "test").deliver(users(:two))

assert_difference "Noticed::Event.count", -1 do
user.destroy
end
end

test "doesn't delete notifications when disabled" do
SimpleNotifier.with(owner: user, message: "test").deliver(users(:two))

assert_no_difference "Noticed::Event.count" do
user.destroy
end
end

def user
@user ||= users(:one)
end
end

0 comments on commit d2cb17a

Please sign in to comment.