ledger 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Ledger
2
2
 
3
- TODO: Write a gem description
3
+ Does your app have the concept of accounts, with multiple users per account?
4
+
5
+ Yes?
6
+
7
+ Great.
8
+
9
+ Ledger will easily allow you to create an activity stream of user events on a per account basis.
4
10
 
5
11
  ## Installation
6
12
 
@@ -18,7 +24,165 @@ Or install it yourself as:
18
24
 
19
25
  ## Usage
20
26
 
21
- TODO: Write usage instructions here
27
+ Start by adding the `HasEvents` module to your account object.
28
+
29
+ ```ruby
30
+ class Account < ActiveRecord::Base
31
+
32
+ include Ledger::HasEvents
33
+
34
+ end
35
+ ```
36
+
37
+ Add in the `CreatesEvents` module to your controller.
38
+
39
+ ```ruby
40
+ class CategoriesController < ApplicationController
41
+
42
+ include Ledger::CreatesEvents
43
+
44
+ end
45
+ ```
46
+
47
+ Now all you need to do is call `#create_event` when you do something.
48
+
49
+ ```ruby
50
+ def update
51
+ @category.update_attributes! params[:category]
52
+ create_event :updateated, @category
53
+ end
54
+ ```
55
+
56
+ Retrieve your event stream like so
57
+
58
+ ```ruby
59
+ account.event_stream.each do |e|
60
+ puts "#{a.actor['name']} #{a.action} #{a.object} #{a.data['name']}"
61
+ end
62
+ "Mal Curtis updated Category Food"
63
+ ```
64
+
65
+ `#event_stream` brings back the last 10 events. Send through an integer to get more.
66
+
67
+ Each event has the following (by default, for options see further down).
68
+
69
+ ```
70
+ {
71
+ "key"=>"category_updated",
72
+ "action"=>"updated",
73
+ "object"=>"Category",
74
+ "actor"=>{
75
+ "id"=>1,
76
+ "email"=>"mal@mal.co.nz",
77
+ "name"=>"Mal Curtis"
78
+ },
79
+ "data"=>{
80
+ "id"=>1515,
81
+ "name"=>"Food"
82
+ },
83
+ "created_at"=>2013-03-03 09:28:59 +1300
84
+ }
85
+ ```
86
+
87
+ Ledger isn’t opinionated about how you display your events in your app. You’ll need to figure that one out.
88
+
89
+ ## Customizing
90
+
91
+ ### Accounts & Users
92
+
93
+ 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.
94
+
95
+ ```ruby
96
+ Ledger.configure do |config|
97
+ config.event_scope_method = :current_account # Or whatevs
98
+ config.event_actor_method = :current_user # as above
99
+ end
100
+ ```
101
+
102
+ ### Moar object data
103
+
104
+ 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.
105
+
106
+ ```ruby
107
+ class User
108
+ include Ledger::HasEvents
109
+ def event_details
110
+ { id: id, email: email, username: username }
111
+ end
112
+ end
113
+
114
+ class Category
115
+ def event_details
116
+ { id: id, parent: parent_id, description: description }
117
+ end
118
+ end
119
+ ```
120
+
121
+ ### Moar event data
122
+
123
+ Want to send more information about events? Just send through the information at the end of the `#create_event` call.
124
+
125
+ ```
126
+ create_event :state_changed, @category, from: from_state, to: @category.state
127
+ ```
128
+ ```
129
+
130
+ {
131
+ "key"=>"category_state_changed",
132
+ "action"=>"state_changed",
133
+ "object"=>"Category",
134
+ "actor"=>{
135
+ "id"=>1,
136
+ "email"=>"mal@mal.co.nz",
137
+ "name"=>"Mal Curtis"
138
+ },
139
+ "data"=>{
140
+ "id"=>1515,
141
+ "name"=>"Food",
142
+ "from"=>"available",
143
+ "to"=>"unavailable"
144
+ },
145
+ "created_at"=>2013-03-03 09:28:59 +1300
146
+ }
147
+ ```
148
+
149
+
150
+ ### Redis connection
151
+
152
+ Ledger defaults to `$redis`. If you want to set this manually, customize it in an initializer. Here's an example:
153
+
154
+ ```ruby
155
+ Ledger.configure do |config|
156
+ uri = URI.parse(ENV["REDISTOGO_URL"] || 'redis://127.0.0.1:6379')
157
+ config.redis = Redis.new(
158
+ :host => uri.host,
159
+ :port => uri.port,
160
+ :password => uri.password
161
+ )
162
+ end
163
+ ```
164
+
165
+ ### Manual Events
166
+
167
+ You can add an event manually by creating an instance of `Ledger::Event`, then adding than in via `account.add_event`.
168
+
169
+ ```ruby
170
+ new_event = Ledger::Event.new key: "manual_event", data: { some: "thing" }
171
+ account.add_event new_event
172
+ ```
173
+
174
+ ### Direct Redis access
175
+
176
+ You can access redis directly through `#events`. This will be a [Nest](https://github.com/soveran/nest) instance, and you can call on this, or use its naming schema to do some other magic.
177
+
178
+ ```ruby
179
+ # Trim the events down to the last 100 events
180
+ account.events.ltrim 0, 100
181
+
182
+ # Create a new redis key (account:xxx:events:something_else)
183
+ account.events["something_else"].lpush "Some data"
184
+ ```
185
+
22
186
 
23
187
  ## Contributing
24
188
 
data/ledger.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
  gem.authors = ["Mal Curtis"]
6
6
  gem.email = ["mal@sitepoint.com"]
7
7
  gem.description = %q{Redis backed account activity streams}
8
- gem.summary = %q{Redis backed account activity streams}
8
+ gem.summary = %q{Creates a per account activity stream for your Saas Ruby app}
9
9
  gem.homepage = ""
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
@@ -14,4 +14,7 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "ledger"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Ledger::VERSION
17
+
18
+ # Declaritive Redis Keys
19
+ gem.add_runtime_dependency "nest"
17
20
  end
data/lib/ledger.rb CHANGED
@@ -1,5 +1,17 @@
1
1
  require "ledger/version"
2
+ require 'ledger/event'
3
+ require 'ledger/has_events'
4
+ require 'ledger/creates_events'
2
5
 
3
6
  module Ledger
4
- # Your code goes here...
7
+ mattr_accessor :event_scope_method, :event_actor_method, :redis
8
+
9
+ @@event_scope_method = :current_account
10
+ @@event_actor_method = :current_user
11
+
12
+ class << self
13
+ def configure
14
+ yield self
15
+ end
16
+ end
5
17
  end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ module Ledger
4
+ module CreatesEvents
5
+ def create_event action, object, data = {}
6
+ unless event_scope.respond_to? :add_event
7
+ raise "#{Ledger.event_scope_method} does not respond to #add_event.
8
+ Either include Ledger::HasEvents in that scope, or set the
9
+ 'event_scope_method' in your Ledger configuration to an
10
+ object that does."
11
+ end
12
+
13
+ object_name = object.class.name.downcase
14
+ key = [object_name, action].join('_')
15
+
16
+ details = {
17
+ key: key,
18
+ action: action,
19
+ object: object_name,
20
+ actor: {},
21
+ data: data || {}
22
+ }
23
+
24
+ details[:data].merge! object.respond_to?(:event_details) ? \
25
+ object.event_details : \
26
+ { id: object.id, name: object.name }
27
+
28
+ details[:actor].merge! event_actor.respond_to?(:event_details) ? \
29
+ event_actor.event_details : \
30
+ { id: event_actor.id, email: event_actor.email, name: event_actor.name }
31
+
32
+ event_scope.add_event Ledger::Event.new(details)
33
+ end
34
+
35
+ def event_scope
36
+ send(Ledger.event_scope_method)
37
+ rescue NoMethodError
38
+ raise "Hey, I tried calling #{Ledger.event_scope_method} but it doesn't exist. You’ll need to set the `event_scope_method` configuration value to the method that returns your current account object."
39
+ end
40
+
41
+ def event_actor
42
+ send(Ledger.event_actor_method)
43
+ rescue NoMethodError
44
+ raise "Hey, I tried calling #{Ledger.event_scope_method} but it doesn't exist. You’ll need to set the `event_actor_method` configuration value to the method that returns your current user object."
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,19 @@
1
+ module Ledger
2
+ class Event
3
+ attr_accessor :actor, :key, :action, :object, :data, :created_at
4
+
5
+ def initialize opts
6
+ opts.each do |attr, value|
7
+ self.send("#{attr}=", value) if respond_to?("#{attr}=")
8
+ end
9
+ self.created_at = Time.now
10
+ end
11
+
12
+ class << self
13
+ def from_json json
14
+ require 'json'
15
+ self.new JSON.parse json
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'nest'
2
+ module Ledger
3
+ module HasEvents
4
+ def rdb
5
+ Nest.new(self.class.name.downcase)[to_param]
6
+ end
7
+
8
+ def self.rdb
9
+ Nest.new(name, Ledger.redis)
10
+ end
11
+
12
+ def event_stream length = 10
13
+ events.lrange(0, length).map do |json|
14
+ Ledger::Event.from_json json
15
+ end
16
+ end
17
+
18
+ def add_event event
19
+ events.lpush event.to_json
20
+ end
21
+
22
+ def events
23
+ rdb[:events]
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Ledger
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ledger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-02 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2013-03-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  description: Redis backed account activity streams
15
31
  email:
16
32
  - mal@sitepoint.com
@@ -25,6 +41,9 @@ files:
25
41
  - Rakefile
26
42
  - ledger.gemspec
27
43
  - lib/ledger.rb
44
+ - lib/ledger/creates_events.rb
45
+ - lib/ledger/event.rb
46
+ - lib/ledger/has_events.rb
28
47
  - lib/ledger/version.rb
29
48
  homepage: ''
30
49
  licenses: []
@@ -49,6 +68,6 @@ rubyforge_project:
49
68
  rubygems_version: 1.8.23
50
69
  signing_key:
51
70
  specification_version: 3
52
- summary: Redis backed account activity streams
71
+ summary: Creates a per account activity stream for your Saas Ruby app
53
72
  test_files: []
54
73
  has_rdoc: