EventPublisher Support for TagMaster events
This commit is contained in:
parent
31deb4cce8
commit
5ae4f20637
7 changed files with 189 additions and 3 deletions
|
@ -5,7 +5,7 @@
|
|||
module Nonprofits
|
||||
class TagMastersController < ApplicationController
|
||||
include Controllers::Nonprofit::Current
|
||||
include Controllers::Nonprofit::Authorization
|
||||
include Controllers::Nonprofit::Authorization
|
||||
before_action :authenticate_nonprofit_user!
|
||||
|
||||
def index
|
||||
|
@ -25,7 +25,7 @@ module Nonprofits
|
|||
|
||||
def destroy
|
||||
tag_master = current_nonprofit.tag_masters.find(params[:id])
|
||||
tag_master.update_attribute(:deleted, true)
|
||||
tag_master.discard!
|
||||
tag_master.tag_joins.destroy_all
|
||||
render json: {}, status: :ok
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ class TagJoin < ApplicationRecord
|
|||
|
||||
def name
|
||||
tag_master.name
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_with_name(nonprofit, h)
|
||||
tm = nonprofit.tag_masters.find_by_name(h['name'])
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
|
||||
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
|
||||
class TagMaster < ApplicationRecord
|
||||
|
||||
# TODO replace with Discard gem
|
||||
define_model_callbacks :discard
|
||||
|
||||
after_discard :publish_delete
|
||||
|
||||
# :nonprofit, :nonprofit_id,
|
||||
# :name,
|
||||
# :deleted,
|
||||
|
@ -11,6 +17,7 @@ class TagMaster < ApplicationRecord
|
|||
validates :name, presence: true
|
||||
validate :no_dupes, on: :create
|
||||
|
||||
after_create :publish_create
|
||||
belongs_to :nonprofit
|
||||
has_many :tag_joins, dependent: :destroy
|
||||
has_one :email_list
|
||||
|
@ -22,4 +29,50 @@ class TagMaster < ApplicationRecord
|
|||
|
||||
errors.add(:base, 'Duplicate tag') if nonprofit.tag_masters.not_deleted.where(name: name).any?
|
||||
end
|
||||
|
||||
|
||||
# TODO replace with discard gem
|
||||
def discard!
|
||||
run_callbacks(:discard) do
|
||||
self.deleted = true
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
def to_builder(*expand)
|
||||
Jbuilder.new do |tag|
|
||||
tag.(self, :id, :name, :deleted)
|
||||
tag.object 'tag_master'
|
||||
if expand.include? :nonprofit && nonprofit
|
||||
tag.nonprofit do
|
||||
tag.id nonprofit.id
|
||||
tag.name nonprofit.name
|
||||
end
|
||||
else
|
||||
tag.nonprofit nonprofit && nonprofit.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def publish_create
|
||||
Houdini.event_publisher.announce(:tag_master_created, to_event('tag_master.created', :nonprofit).attributes!)
|
||||
end
|
||||
|
||||
def publish_delete
|
||||
Houdini.event_publisher.announce(:tag_master_deleted, to_event('tag_master.deleted', :nonprofit).attributes!)
|
||||
end
|
||||
|
||||
|
||||
def to_event(event_type, *expand)
|
||||
Jbuilder.new do |event|
|
||||
event.id SecureRandom.uuid
|
||||
event.object 'event'
|
||||
event.type event_type
|
||||
event.data do
|
||||
event.object to_builder(*expand)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
20
docs/event_definitions/Nonprofit/TagMaster.ts
Normal file
20
docs/event_definitions/Nonprofit/TagMaster.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
|
||||
import type { HoudiniEvent, HoudiniObject, IdType } from "../common";
|
||||
import type Nonprofit from './';
|
||||
|
||||
export interface TagMaster extends HoudiniObject {
|
||||
deleted: boolean;
|
||||
name: string;
|
||||
nonprofit: IdType | Nonprofit;
|
||||
object: 'tag_master';
|
||||
}
|
||||
|
||||
/** POST /nonprofits/:id/tag_masters */
|
||||
export interface CreateTagMaster {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type TagMasterCreated = HoudiniEvent<'tag_master.created', TagMaster>;
|
||||
|
||||
export type TagMasterDeleted = HoudiniEvent<'tag_master.deleted', TagMaster>;
|
10
docs/event_definitions/Nonprofit/index.ts
Normal file
10
docs/event_definitions/Nonprofit/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
import type { HoudiniObject } from '../common';
|
||||
|
||||
/**
|
||||
* A single nonprofit organization on Houdini.
|
||||
*/
|
||||
export default interface Nonprofit extends HoudiniObject {
|
||||
name: string;
|
||||
object: "nonprofit";
|
||||
}
|
48
docs/event_definitions/common.ts
Normal file
48
docs/event_definitions/common.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* the main identifier for HoudiniObjects which is unique between all other HoudiniObjects with the same object value.
|
||||
* Currently just an integer but we could reevaluate later;
|
||||
*/
|
||||
export type IdType = number;
|
||||
|
||||
/**
|
||||
* Every object controlled by the Houdini event publisher must meet this standard interface
|
||||
* and will inherit from it.
|
||||
*/
|
||||
export interface HoudiniObject {
|
||||
/**
|
||||
* An IdType which unique which uniquely identifies this object
|
||||
* from all other similar objects
|
||||
*/
|
||||
id: IdType;
|
||||
/**
|
||||
* the type of object. Roughly corresponds to the object's class in Rails
|
||||
*/
|
||||
object: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event published by Houdini
|
||||
*
|
||||
* Generics:
|
||||
* * EventType a snake-cased string of the format: "<object_type>.<event_name>". As an example
|
||||
* tag_master.created means the event fired by when a tag_master was created
|
||||
* * DataObject: the interface representing the actual object which the event occurred on. An object of that type is
|
||||
* on the 'data' attribute
|
||||
*/
|
||||
export interface HoudiniEvent<EventType extends string, DataObject extends HoudiniObject> {
|
||||
/** data for the event. We wrap the object inside becuase we might want to provide some sort of */
|
||||
data: {
|
||||
/** the object after the event has occurred */
|
||||
object: DataObject;
|
||||
};
|
||||
/**
|
||||
* A UUID uniquely representing the event
|
||||
*/
|
||||
id: string;
|
||||
object: 'event';
|
||||
/** The type of event that this is */
|
||||
type: EventType;
|
||||
|
||||
}
|
55
spec/models/tag_master_spec.rb
Normal file
55
spec/models/tag_master_spec.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
|
||||
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TagMaster, type: :model do
|
||||
include_context :shared_donation_charge_context
|
||||
let(:name) { "TAGNAME"}
|
||||
|
||||
let(:tag_master) { nonprofit.tag_masters.create(name: name) }
|
||||
it 'creates' do
|
||||
expect(tag_master.errors).to be_empty
|
||||
end
|
||||
|
||||
it 'announces create' do
|
||||
expect(Houdini.event_publisher).to receive(:announce).with(:tag_master_created, {
|
||||
'id' => kind_of(String),
|
||||
'object' => 'event',
|
||||
'type' => 'tag_master.created',
|
||||
'data' => {
|
||||
'object' => {
|
||||
'id'=> kind_of(Numeric),
|
||||
'deleted' => false,
|
||||
'name' => name,
|
||||
'nonprofit'=> nonprofit.id,
|
||||
'object' => 'tag_master'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
tag_master
|
||||
end
|
||||
|
||||
it 'announces deleted' do
|
||||
expect(Houdini.event_publisher).to receive(:announce).with(:tag_master_created, anything).ordered
|
||||
expect(Houdini.event_publisher).to receive(:announce).with(:tag_master_deleted, {
|
||||
'id' => kind_of(String),
|
||||
'object' => 'event',
|
||||
'type' => 'tag_master.deleted',
|
||||
'data' => {
|
||||
'object' => {
|
||||
'id'=> kind_of(Numeric),
|
||||
'deleted' => true,
|
||||
'name' => name,
|
||||
'nonprofit'=> nonprofit.id,
|
||||
'object' => 'tag_master'
|
||||
}
|
||||
}
|
||||
}).ordered
|
||||
|
||||
tag_master.discard!
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue