neeto-activities-nano
The nano that manages backend structure for activities.
Schema
create_table :neeto_activities_engine_activities, id: :uuid do |t|
t.references :trackable, polymorphic: true, index: true, type: :uuid
t.references :performer, polymorphic: true, type: :uuid
t.string :key
t.jsonb :metadata, default: {}
t.timestamps
end
Usage
Example
Check an example of an activity generated for updating the ticket status in neetoDesk.
#<NeetoActivitiesEngine::Activity:0x000000013237f158> {
:id => "d0458158-68d1-423f-b364-d22a8916f6d0",
:key => "activity.ticket.update.status",
:trackable_type => "Ticket",
:trackable_id => "c5104a50-2eff-49a3-accb-f2fa8f4fc1f7",
:performer_type => "User",
:performer_id => "b028d29e-f40a-4c09-9222-357cfe84e2c3",
:created_at => Mon, 30 Oct 2023 10:23:26.705884000 UTC +00:00,
:updated_at => Mon, 30 Oct 2023 10:23:26.705884000 UTC +00:00,
:metadata => {
"new_value" => "trash",
"old_value" => "open"
}
}
Concern
We have a concern that can be included in the models that need to track the activities,
this concern adds associations and a helper method that allows creating activities easily.
Refer: NeetoActivitiesEngine::Trackable
Example:
class User
include NeetoActivitiesEngine::Trackable
after_save :log_account_block_activity!, if: :blocked?
private
def log_account_block_activity!
old_value, new_value = saved_change_to_blocked_at
key = new_value ? "activity.user.blocked" : "activity.user.unblocked"
metadata = { performer_name: User.current&.name }
log_activity!(key:, metadata:, performer: User.current)
end
end
Complex implementation
neetoDesk needs many custom activities for tickets,
in order to achieve it,
we have created another concern that works on top of the above concern.
Refer: app/models/concerns/trackable/tickets.rb
Usage:
class Ticket
include NeetoActivitiesEngine::Trackable
include Trackable::Tickets
end
Use different provider than User.current
Using User.current
is not a good practice,
it also does not fit in all the places.
Example: In neetoDesk, Automation rules can update tickets,
here the performer is Automation::Rule
not User
.
To get around this problem, we have activity_performer
attr_accessor.
class Ticket
include NeetoActivitiesEngine::Trackable
after_save :log_status_activity!, if: :saved_change_to_status?
private
def log_status_activity!
old_value, new_value = saved_change_to_status
key = "activity.ticket.status.update"
metadata = { old_value:, new_value: }
log_activity!(key: , metadata:, performer: activity_performer)
end
end
ticket.activity_performer = Automation::Rule.first
ticket.update(status: :closed)
Skip an activity in a special case?
Occationally, the business logic demands to skip the activity.
For this, we have added skip_activity
attr_accessor in the concern.
Example:
Assume that you want to skip the activities when you update the ticket from Rails console.
class Ticket
include NeetoActivitiesEngine::Trackable
after_save :log_status_activity!, if: :saved_change_to_status?
private
def log_status_activity!
old_value, new_value = saved_change_to_status
key = "activity.ticket.status.update"
metadata = { old_value:, new_value: }
log_activity!(key: , metadata:, performer: activity_performer)
end
end
ticket.skip_activity = true
ticket.update(status: :closed)