ledger 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: