Does your app have the concept of accounts, with multiple users per account?
Yes?
Great.
Ledger will easily allow you to create an activity stream of user events on a per account basis.
Installation
Add this line to your application's Gemfile:
gem 'ledger'
And then execute:
$ bundle
Or install it yourself as:
$ gem install ledger
Usage
Start by adding the HasEvents
module to your account object.
class Accounts
…
include Ledger::HasEvents
…
end
Add in the CreatesEvents
module to your controller.
class CategoriesController
…
include Ledger::CreatesEvents
…
end
Now all you need to do is call #create_event
when you do something.
def update
@category.update_attributes! params[:category]
create_event :updated, @category
end
Retrieve your event stream like so
account.event_stream.each do |e|
puts "#{a.actor['name']} #{a.action} #{a.object} #{a.data['name']}"
end
"Mal Curtis updated Category Food"
#event_stream
brings back the last 10 events. Send through an integer to get more.
Each event has the following (by default, for options see further down).
{
"action"=>"updated",
"object"=>"Category",
"actor"=>{
"id"=>1,
"email"=>"[email protected]",
"name"=>"Mal Curtis"
},
"data"=>{
"id"=>1515,
"name"=>"Food"
},
"created_at"=>2013-03-03 09:28:59 +1300
}
Ledger isn’t opinionated about how you display your events in your app. You’ll need to figure that one out.
Customizing
Accounts & Users
Ledger expects there to be a current_account
and current_user
method when creating an event. If this doesn’t suit your app, smash this into an initializer.
Ledger.configure do |config|
config.event_scope_method = :current_account # Or whatevs
config.event_actor_method = :current_user # as above
end
Moar object data
Ledger will try and add id
, email
and name
from your user object and id
and name
from the object passed to #create_event
. If you don’t have some of these methods, or want to add more information, just define #event_details
and return a hash.
class User
include Ledger::HasEvents
def event_details
{ id: id, email: email, username: username }
end
end
class Category
def event_details
{ id: id, parent: parent_id, description: description }
end
end
Moar event data
Want to send more information about events? Just send through the information at the end of the #create_event
call.
create_event :state_changed, @category, from: from_state, to: @category.state
{
"action"=>"state_changed",
"object"=>"Category",
"actor"=>{
"id"=>1,
"email"=>"[email protected]",
"name"=>"Mal Curtis"
},
"data"=>{
"id"=>1515,
"name"=>"Food",
"from"=>"available",
"to"=>"unavailable"
},
"created_at"=>2013-03-03 09:28:59 +1300
}
Redis connection
Ledger defaults to $redis
. If you want to set this manually, customize it in an initializer. Here's an example:
Ledger.configure do |config|
uri = URI.parse(ENV["REDISTOGO_URL"] || 'redis://127.0.0.1:6379')
config.redis = Redis.new(
:host => uri.host,
:port => uri.port,
:password => uri.password
)
end
Manual Events
You can add an event manually by creating an instance of Ledger::Event
, then adding that in via account.add_event
.
new_event = Ledger::Event.new action: "create", object: "manual_event", data: { some: "thing" }
account.add_event new_event
Direct Redis access
You can access redis directly through #events
. This will be a Nest instance and you can call on it, or use its naming schema to do some other magic.
# Trim the events down to the last 100 events
account.events.ltrim 0, 100
# Create a new redis key (account:xxx:events:something_else)
account.events["something_else"].lpush "Some data"
Who
Created with love by Mal Curtis
Twitter: snikchnz
License
MIT. See license file.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request