All Projects → krisleech → wisper-activerecord

krisleech / wisper-activerecord

Licence: MIT license
Transparently publish all model changes to subscribers

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to wisper-activerecord

active record distinct on
Support for `DISTINCT ON` statements when querying with ActiveRecord
Stars: ✭ 23 (-76.29%)
Mutual labels:  activerecord
AlamoRecord
An elegant yet powerful iOS networking layer inspired by ActiveRecord.
Stars: ✭ 18 (-81.44%)
Mutual labels:  activerecord
ar-dynattribute
Provide ActiveRecord dynamic attributes stored into the single field in serialized state
Stars: ✭ 43 (-55.67%)
Mutual labels:  activerecord
activerecord-shard for
Database Sharding Library for ActiveRecord
Stars: ✭ 16 (-83.51%)
Mutual labels:  activerecord
ar-variation
Variation behavior for ActiveRecord
Stars: ✭ 46 (-52.58%)
Mutual labels:  activerecord
rails async migrations
Asynchronous support for ActiveRecord::Migration
Stars: ✭ 56 (-42.27%)
Mutual labels:  activerecord
activeentity
Active Record without Database
Stars: ✭ 46 (-52.58%)
Mutual labels:  activerecord
computed model
Batch loader with dependency resolution and computed fields
Stars: ✭ 22 (-77.32%)
Mutual labels:  activerecord
ActiveRecord
New Active Record for KumbiaPHP
Stars: ✭ 23 (-76.29%)
Mutual labels:  activerecord
mv-core
Migration Validators project core classes
Stars: ✭ 23 (-76.29%)
Mutual labels:  activerecord
ar-role
ActiveRecord behavior, which provides relation roles (table inheritance)
Stars: ✭ 34 (-64.95%)
Mutual labels:  activerecord
workflow-activerecord
ActiveRecord/Rails Integration for the Workflow library
Stars: ✭ 24 (-75.26%)
Mutual labels:  activerecord
rails cursor pagination
Add cursor pagination to your ActiveRecord backed application
Stars: ✭ 21 (-78.35%)
Mutual labels:  activerecord
yii2-rest-client
REST client (AR-like model) for Yii Framework 2.0 (via yii2-http-client)
Stars: ✭ 19 (-80.41%)
Mutual labels:  activerecord
models stats
Charts for your rails models with MetricsGraphics.js and NVD3
Stars: ✭ 43 (-55.67%)
Mutual labels:  activerecord
siphon
Siphon enables you to easily combine your scopes with params
Stars: ✭ 23 (-76.29%)
Mutual labels:  activerecord
defaults
Add default value for ActiveRecord attributes
Stars: ✭ 16 (-83.51%)
Mutual labels:  activerecord
rails-countries
Integration between Rails and countries gem.
Stars: ✭ 17 (-82.47%)
Mutual labels:  activerecord
wp-activerecord
An ActiveRecord implementation for WordPress
Stars: ✭ 19 (-80.41%)
Mutual labels:  activerecord
zen-query
parascope gem for param-based scope generation
Stars: ✭ 25 (-74.23%)
Mutual labels:  activerecord

Wisper::ActiveRecord

Gem Version Code Climate Build Status

Transparently publish model lifecycle events to subscribers.

Using Wisper events is a better alternative to ActiveRecord callbacks and Observers.

Listeners are subscribed to models at runtime.

Installation

gem 'wisper-activerecord'

Usage

Setup a publisher

class Meeting < ActiveRecord::Base
  include Wisper.model

  # ...
end

If you wish all models to broadcast events without having to explicitly include Wisper.model add the following to an initializer:

Wisper::ActiveRecord.extend_all

Subscribing

Subscribe a listener to model instances:

meeting = Meeting.new
meeting.subscribe(Auditor.new)

Subscribe a block to model instances:

meeting.on(:create_meeting_successful) { |meeting| ... }

Subscribe a listener to all instances of a model:

Meeting.subscribe(Auditor.new)

Please refer to the Wisper README for full details about subscribing.

The events which are automatically broadcast are:

  • after_create
  • after_update
  • after_destroy
  • create_<model_name>_{successful, failed}
  • update_<model_name>_{successful, failed}
  • destroy_<model_name>_successful
  • <model_name>_committed
  • after_commit
  • after_rollback

Reacting to Events

To receive an event the listener must implement a method matching the name of the event with a single argument, the instance of the model.

def create_meeting_successful(meeting)
  # ...
end

Example

Controller

class MeetingsController < ApplicationController
  def new
    @meeting = Meeting.new
  end

  def create
    @meeting = Meeting.new(params[:meeting])
    @meeting.subscribe(Auditor.new)
    @meeting.on(:create_meeting_successful) { redirect_to meeting_path }
    @meeting.on(:create_meeting_failed)     { render action: :new }
    @meeting.save
  end

  def edit
    @meeting = Meeting.find(params[:id])
  end

  def update
    @meeting = Meeting.find(params[:id])
    @meeting.subscribe(Auditor.new)
    @meeting.on(:update_meeting_successful) { redirect_to meeting_path }
    @meeting.on(:update_meeting_failed)     { render :action => :edit }
    @meeting.update_attributes(params[:meeting])
  end
end

Using on to subscribe a block to handle the response is optional, you can still use if @meeting.save if you prefer.

Listener

Which simply records an audit in memory

class Auditor

  def after_create(subject)
    push_audit_for('create', subject)
  end

  def after_update(subject)
    push_audit_for('update', subject)
  end

  def after_destroy(subject)
    push_audit_for('destroy', subject)
  end

  def self.audit
    @audit ||= []
  end

  private

  def push_audit_for(action, subject)
    self.class.audit.push(audit_for(action, subject))
  end

  def audit_for(action, subject)
    {
      action: action,
      subject_id: subject.id,
      subject_class: subject.class.to_s,
      changes: subject.previous_changes,
      created_at: Time.now
    }
  end
end

Do some CRUD

Meeting.create(:description => 'Team Retrospective', :starts_at => Time.now + 2.days)

meeting = Meeting.find(1)
meeting.starts_at = Time.now + 2.months
meeting.save

And check the audit

Auditor.audit # => [...]

Notes on Testing

ActiveRecord <= 4.0

This gem makes use of ActiveRecord's after_commit lifecycle hook to broadcast events, which will create issues when testing with transactional fixtures. Unless you also include the test_after_commit gem ActiveRecord models will not broadcast any lifecycle events within your tests.

Compatibility

Tested on CRuby, Rubinius and JRuby for ActiveRecord ~> 3.0, ~> 4.0, and ~> 5.0.

See the CI build status for more information.

Contributing

Please submit a Pull Request with specs.

Running the specs

bundle exec rspec
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].