Plugin for event logging in rails application.
Read our article (sorry French only)
Add this line to your application's Gemfile :
gem'event_logging',git: 'git@github.com:Snapp-FidMe/event-logging.git',branch: :masterImport migrations with :
bundle exec event_logging:install:migrationsRequire Rails 5. or later and Postgresql with jsonb (9.6 or greater).
Configure database in test/dummy/config/database.yml then play migrations :
RAILS_ENV=test bundle exec rake db:migrateAnd launch tests :
bundle exec rake testEvents carry this data :
- stream_id => Write model ID
- aggregate_name => Model name
- action => operation which raised event (create, update, destroy or custom)
- created_at
- payload => hash that contains model changes
Write models are business logic models. Use the Writer concern :
classReward < ApplicationRecordincludeEventLogging::Writer# Business stuffendThen after each create or update an event will be inserted in database, and associated read models will have to manage the event.
All the process is in callback transaction so data will be consistent over exceptions.
Write model can dispatch custom events :
reward.dispatch_event_log!('custom_action','the'=>'payload')Read models are data projection. Use the Reader concern :
classRewardLog < ApplicationRecordincludeEventLogging::Readerregister_write_models:reward,:retailerclass << selfdefhandle_event_log(event)ifevent.aggregate_name == Reward.namehandle_reward_event_log(event)elsifevent.aggregate_name == Retailer.namehandle_retailer_event_log(event)endenddefhandle_reward_event_log(event)ifevent.action == 'create'RewardLog.create!(reward_id: event.stream_id,status: event.payload['status'][1],retailer_id: event.payload['retailer_id'][1]retailer_name: Retailer.find(event.payload['retailer_id'][1]).name)elsifevent.action == 'update' && event.payload.has_key?['status']reward=Reward.find(event.stream_id)RewardLog.create!(reward_id: event.stream_id,status: event.payload['status'][1],retailer_id: reward.retailer.idretailer_name: reward.retailer.name)endenddefhandle_retailer_event_log(event)ifevent.payload.has_key?('name')Reward.where(retailer_id: event.stream_id).find_eachdo |reward|
reward.update_attributes!(retailer_name: event.payload['name'][1])endendendendendDefault payload is saved_changes from Rails.
Be careful : synchronised read models slow write operations in order to speed up read operations.