memorable 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +161 -0
- data/lib/memorable/controller.rb +7 -12
- data/lib/memorable/model.rb +4 -3
- data/lib/memorable/{configuration.rb → registration.rb} +2 -8
- data/lib/memorable/template_engine.rb +22 -78
- data/lib/memorable/template_engines/default.rb +79 -0
- data/lib/memorable/version.rb +1 -1
- data/lib/memorable.rb +11 -5
- data/memorable.gemspec +3 -3
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4605915b94644c1cf4eec46d551ea971637c61b
|
4
|
+
data.tar.gz: 1d8e9deda6b5a1cb73dd82cd078d2bc108234a2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 017ee728f18ac91a52790617457d9910e6f9025a14ef2d75c34ecff817bc67dcb6ecf4ffca203b18dc85311d540643c65eb27dcc0749fc49197a58ec59b7a860
|
7
|
+
data.tar.gz: 420b4c3b0b1cdc0482dbdbf7768c59911fc3b1f0de0f74d00b2f7dd2d6602ca96327e3db475815161ee01d67a452712968ccbdd8f831124b0865a2801a314142
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# Memorable
|
2
|
+
|
3
|
+
A Rails logging system based on actions instead of model callbacks. Customizable ready-to-run configurations and built-in I18n support.
|
4
|
+
|
5
|
+
**Note**
|
6
|
+
It's released on [RubyGems](https://rubygems.org/gems/memorable).
|
7
|
+
If something doesn't work, feel free to report a bug or start an issue.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'memorable'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install memorable
|
24
|
+
|
25
|
+
If you prefer to use the latest code, you can build from source:
|
26
|
+
|
27
|
+
```
|
28
|
+
gem build memorable.gemspec
|
29
|
+
gem install memorable-<VERSION>.gem
|
30
|
+
```
|
31
|
+
|
32
|
+
## Configuration
|
33
|
+
|
34
|
+
### Initializer
|
35
|
+
|
36
|
+
Write these lines of code to your configuration file, for example, `memorable.rb`.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
Memorable.setup do |config|
|
40
|
+
config.journals_model = Journal
|
41
|
+
|
42
|
+
# Specify template engine, default
|
43
|
+
# config.template_engine = DefaultYAMLEngine
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
And put it under `config/initiailizers` directory of your Rails project.
|
48
|
+
|
49
|
+
Or require this file manually by yourself.
|
50
|
+
|
51
|
+
### Migration
|
52
|
+
|
53
|
+
Create a migration file as following:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
class CreateJournal < ActiveRecord::Migration
|
57
|
+
def up
|
58
|
+
create_table :journals do |t|
|
59
|
+
t.integer :user_id
|
60
|
+
t.integer :resource_id
|
61
|
+
t.string :resource_type
|
62
|
+
t.text :meta
|
63
|
+
|
64
|
+
t.timestamps
|
65
|
+
end
|
66
|
+
|
67
|
+
add_index :journals, :user_id
|
68
|
+
add_index :journals, :resource_id
|
69
|
+
|
70
|
+
# If you are not using globalize, https://github.com/globalize/globalize,
|
71
|
+
# comment this line and add a field named content into your journals table.
|
72
|
+
# eg: t.text :content
|
73
|
+
Journal.create_translation_table! :content => :text
|
74
|
+
end
|
75
|
+
|
76
|
+
def down
|
77
|
+
remove_index :journals, :user_id
|
78
|
+
remove_index :journals, :resource_id
|
79
|
+
|
80
|
+
drop_table :journals
|
81
|
+
|
82
|
+
# If you are not using globalize, comment this line
|
83
|
+
Journal.drop_translation_table!
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
And then execute:
|
89
|
+
|
90
|
+
$ bundle exec rake db:migrate
|
91
|
+
|
92
|
+
This will give you a journals table.
|
93
|
+
|
94
|
+
### Model
|
95
|
+
|
96
|
+
Create a ActiveRecord Model, and you are all set.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class Journal < ActiveRecord::Base
|
100
|
+
attr_accessible :resource_id, :resource_type, :user_id, :meta, :content
|
101
|
+
|
102
|
+
store :meta, accessors: [:controller, :action, :template_key ]
|
103
|
+
|
104
|
+
# If you are not using globalize, comment this line
|
105
|
+
translates :content, :fallbacks_for_empty_translations => true
|
106
|
+
|
107
|
+
belongs_to :user
|
108
|
+
belongs_to :resource, polymorphic: true, :touch => true
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
## Usage
|
113
|
+
|
114
|
+
Add your own templates using yaml, this gem ships with a default yml template engine.
|
115
|
+
|
116
|
+
Put your templates under `app/views/memorable` directory of you project, and name them with something like `en_US.yml`
|
117
|
+
|
118
|
+
Here's an example of a typical template file
|
119
|
+
|
120
|
+
```
|
121
|
+
defaults:
|
122
|
+
create:
|
123
|
+
base: "%{resource_type} created."
|
124
|
+
update:
|
125
|
+
base: "%{resource_type} updated."
|
126
|
+
destroy:
|
127
|
+
base: "%{resource_type} deleted."
|
128
|
+
others:
|
129
|
+
base: "%{action} was executed on %{resource_type}."
|
130
|
+
contacts:
|
131
|
+
create:
|
132
|
+
base: "Added vendor %{name} to Vendor Library."
|
133
|
+
update:
|
134
|
+
base: "Edited information for Vendor %{name}."
|
135
|
+
name: "Change Vendor Name form %{previous_name} to %{name}."
|
136
|
+
destroy:
|
137
|
+
base: "Deleted Vendor %{name}."
|
138
|
+
```
|
139
|
+
|
140
|
+
As you can see, controller_name and action_name are used as the first two levels of template_keys.
|
141
|
+
|
142
|
+
And it support variable interpolation, default attributes, previous_changed attributes, controller_name, action_name, resource_type are included in default local variables.
|
143
|
+
|
144
|
+
## Advanced Usage
|
145
|
+
|
146
|
+
You can pass addition local variables used in template interpolation, or even specify which template you would like to use.
|
147
|
+
|
148
|
+
You can achieve this by define a method named `"memorable_#{action_name}"` in your controller and return a hash with additional local variables and template_key you would like to use.
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class ContactsController < ApplicationController
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def memorable_update
|
156
|
+
if @contact.previous_changes.key? [:name]
|
157
|
+
{template_key: 'name', company_email: @contact.company.email}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
```
|
data/lib/memorable/controller.rb
CHANGED
@@ -15,7 +15,7 @@ module Memorable
|
|
15
15
|
locals = extract_memorable_locals
|
16
16
|
|
17
17
|
# write to database
|
18
|
-
|
18
|
+
Memorable.config.journals_model.create_with_options!(locals)
|
19
19
|
|
20
20
|
rescue Exception => e
|
21
21
|
raise e if Rails.env.development? # for debug
|
@@ -23,8 +23,8 @@ module Memorable
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def memorable?
|
26
|
-
|
27
|
-
|
26
|
+
Registration.registered?(controller_name, action_name) &&
|
27
|
+
Registration.condition_matched?(self) &&
|
28
28
|
response.successful?
|
29
29
|
end
|
30
30
|
|
@@ -44,16 +44,11 @@ module Memorable
|
|
44
44
|
})
|
45
45
|
end
|
46
46
|
|
47
|
-
# # Journals Model is free to override the behavior of this method
|
48
|
-
# if journal.respond_to? :set_attributes_for_event
|
49
|
-
# journal.set_attributes_for_event(controller)
|
50
|
-
# end
|
51
|
-
|
52
47
|
custom_method_name = "memorable_#{action_name}"
|
53
48
|
|
54
|
-
if respond_to? custom_method_name
|
49
|
+
if respond_to? custom_method_name, true
|
55
50
|
custom_locals = self.send custom_method_name
|
56
|
-
locals.merge!(custom_locals)
|
51
|
+
locals.merge!(custom_locals) if custom_locals.is_a?(Hash)
|
57
52
|
end
|
58
53
|
|
59
54
|
locals
|
@@ -64,7 +59,7 @@ module Memorable
|
|
64
59
|
end
|
65
60
|
|
66
61
|
def memorable_resource_name
|
67
|
-
|
62
|
+
Registration.resource_name(controller_name) || controller_name.singularize
|
68
63
|
end
|
69
64
|
|
70
65
|
module ClassMethods
|
@@ -100,7 +95,7 @@ module Memorable
|
|
100
95
|
private
|
101
96
|
|
102
97
|
def memorize_actions(action_names, options, condition_proc)
|
103
|
-
|
98
|
+
Registration.register action_names, controller_name, options, condition_proc
|
104
99
|
end
|
105
100
|
|
106
101
|
def all_actions
|
data/lib/memorable/model.rb
CHANGED
@@ -6,9 +6,9 @@ module Memorable
|
|
6
6
|
def write_content(options)
|
7
7
|
current_locale = I18n.locale
|
8
8
|
|
9
|
-
|
10
|
-
I18n.locale
|
11
|
-
content
|
9
|
+
Memorable.config.template_engine.assemble(options).each do |template|
|
10
|
+
I18n.locale = template[0]
|
11
|
+
self.content = template[1]
|
12
12
|
end
|
13
13
|
|
14
14
|
I18n.locale = current_locale
|
@@ -26,6 +26,7 @@ module Memorable
|
|
26
26
|
journal.user_id = options.delete :user_id
|
27
27
|
journal.resource_id = options.delete :resource_id
|
28
28
|
journal.resource_type = options.delete :resource_type
|
29
|
+
journal.meta = options if journal.respond_to?(:meta)
|
29
30
|
|
30
31
|
journal.write_content(options)
|
31
32
|
journal
|
@@ -1,15 +1,9 @@
|
|
1
1
|
module Memorable
|
2
|
-
class
|
2
|
+
class Registration
|
3
3
|
@register_actions = {}
|
4
|
-
@journals_model = nil
|
5
4
|
|
6
5
|
class << self
|
7
|
-
attr_reader :register_actions
|
8
|
-
|
9
|
-
def journals_model=(model)
|
10
|
-
model_klass = Object.const_get model.capitalize
|
11
|
-
@journals_model = model_klass
|
12
|
-
end
|
6
|
+
attr_reader :register_actions
|
13
7
|
|
14
8
|
def register(action_names, controller_name, options, condition_proc)
|
15
9
|
register_actions[controller_name] ||= {}
|
@@ -1,10 +1,25 @@
|
|
1
1
|
require 'singleton'
|
2
|
-
require 'yaml'
|
3
2
|
|
4
3
|
module Memorable
|
4
|
+
|
5
|
+
# This is an abstract class, do not use it directly. Inherit from this class
|
6
|
+
# and implement custom load!/parse/render medthods.
|
5
7
|
class TemplateEngine
|
6
8
|
include Singleton
|
7
9
|
|
10
|
+
# Class Methods
|
11
|
+
# --------------------------
|
12
|
+
# Override this method in subclass
|
13
|
+
def self.load!
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.assemble(*args)
|
17
|
+
instance.assemble(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Instance Methods
|
21
|
+
# --------------------------
|
22
|
+
#
|
8
23
|
attr_reader :load_path, :templates
|
9
24
|
|
10
25
|
def initialize
|
@@ -12,88 +27,17 @@ module Memorable
|
|
12
27
|
@templates = {}
|
13
28
|
end
|
14
29
|
|
15
|
-
def store_templates
|
16
|
-
load_path.each do |filename|
|
17
|
-
locale = File.basename(filename, ".yml")
|
18
|
-
data = load_yml filename
|
19
|
-
templates[locale.to_sym] = data
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Loads a YAML template file. The data must have locales as
|
24
|
-
# toplevel keys.
|
25
|
-
def load_yml(filename)
|
26
|
-
begin
|
27
|
-
YAML.load_file(filename)
|
28
|
-
rescue TypeError, ScriptError, StandardError => e
|
29
|
-
raise InvalidYAMLData.new(filename, e.inspect)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
30
|
def assemble(options)
|
34
|
-
|
35
|
-
content =
|
31
|
+
parse(options[:controller], options[:action], options[:template_key]).map do |locale, template|
|
32
|
+
content = render(template, options)
|
36
33
|
[locale, content]
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
def render_template(template, locals)
|
43
|
-
if locals
|
44
|
-
I18n.interpolate(template, locals)
|
45
|
-
else
|
46
|
-
template
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def action_templates(controller, action, sub_key)
|
51
|
-
sub_key ||= 'base'
|
52
|
-
raw_templates = catch(:template_found) do
|
53
|
-
parse_entry(controller, action, sub_key)
|
54
|
-
parse_entry(controller, 'other', sub_key)
|
55
|
-
parse_entry('defaults', action, sub_key)
|
56
|
-
parse_entry('defaults', 'other', sub_key)
|
57
|
-
nil
|
58
|
-
end
|
59
|
-
raise TemplateNotFound, "Template: #{controller} #{action} #{sub_key} not found" unless raw_templates
|
60
|
-
raw_templates
|
61
|
-
end
|
62
|
-
|
63
|
-
def parse_entry(controller, action, sub_key)
|
64
|
-
raw_templates = templates.map do |locale, template_data|
|
65
|
-
template = template_data[controller][action][sub_key] rescue nil
|
66
|
-
template ? [locale, template] : nil
|
67
|
-
end.compact
|
68
|
-
throw :template_found, raw_templates unless raw_templates.blank?
|
69
|
-
end
|
70
|
-
|
71
|
-
# Class Methods
|
72
|
-
# ----------------------
|
73
|
-
#
|
74
|
-
def self.load!
|
75
|
-
pattern = self.pattern_from I18n.available_locales
|
76
|
-
|
77
|
-
add("templates/#{pattern}.yml")
|
78
|
-
add("app/views/memorable/#{pattern}.yml", Rails.root) if defined?(Rails)
|
79
|
-
|
80
|
-
instance.store_templates
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.assemble(*args)
|
84
|
-
instance.assemble(*args)
|
85
|
-
end
|
86
|
-
|
87
|
-
protected
|
88
|
-
|
89
|
-
def self.add(pattern, base_dir=File.dirname(__FILE__))
|
90
|
-
files = Dir[File.join(base_dir, pattern)]
|
91
|
-
instance.load_path.concat(files)
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.pattern_from(args)
|
95
|
-
array = Array(args || [])
|
96
|
-
array.blank? ? '*' : "{#{array.join ','}}"
|
37
|
+
# Override this method in subclass
|
38
|
+
def parse(controller, action, sub_key)
|
97
39
|
end
|
98
40
|
end
|
99
41
|
end
|
42
|
+
|
43
|
+
require 'memorable/template_engines/default'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Memorable
|
4
|
+
class DefaultYAMLEngine < TemplateEngine
|
5
|
+
|
6
|
+
# Class Methods
|
7
|
+
# --------------------------
|
8
|
+
# load yaml templates
|
9
|
+
def self.load!
|
10
|
+
pattern = self.pattern_from I18n.available_locales
|
11
|
+
|
12
|
+
add("memorable/templates/#{pattern}.yml", Memorable.config.default_templates_directory)
|
13
|
+
add("app/views/memorable/#{pattern}.yml", Rails.root) if defined?(Rails)
|
14
|
+
|
15
|
+
instance.store_templates
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.add(pattern, base_dir)
|
19
|
+
files = Dir[File.join(base_dir, pattern)]
|
20
|
+
instance.load_path.concat(files)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.pattern_from(args)
|
24
|
+
array = Array(args || [])
|
25
|
+
array.blank? ? '*' : "{#{array.join ','}}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Instance Methods
|
29
|
+
# --------------------------
|
30
|
+
#
|
31
|
+
def store_templates
|
32
|
+
load_path.each do |filename|
|
33
|
+
locale = File.basename(filename, ".yml")
|
34
|
+
data = load_yml filename
|
35
|
+
templates[locale.to_sym] = data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse(controller, action, sub_key)
|
40
|
+
sub_key ||= 'base'
|
41
|
+
raw_templates = catch(:template_found) do
|
42
|
+
parse_entry(controller, action, sub_key)
|
43
|
+
parse_entry(controller, 'other', sub_key)
|
44
|
+
parse_entry('defaults', action, sub_key)
|
45
|
+
parse_entry('defaults', 'other', sub_key)
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
raise TemplateNotFound, "Template: #{controller} #{action} #{sub_key} not found" unless raw_templates
|
49
|
+
raw_templates
|
50
|
+
end
|
51
|
+
|
52
|
+
def render(template, locals)
|
53
|
+
if locals
|
54
|
+
I18n.interpolate(template, locals)
|
55
|
+
else
|
56
|
+
template
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Loads a YAML template file.
|
63
|
+
def load_yml(filename)
|
64
|
+
begin
|
65
|
+
YAML.load_file(filename)
|
66
|
+
rescue TypeError, ScriptError, StandardError => e
|
67
|
+
raise InvalidYAMLData.new(filename, e.inspect)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_entry(controller, action, sub_key)
|
72
|
+
raw_templates = templates.map do |locale, template_data|
|
73
|
+
template = template_data[controller][action][sub_key] rescue nil
|
74
|
+
template ? [locale, template] : nil
|
75
|
+
end.compact
|
76
|
+
throw :template_found, raw_templates unless raw_templates.blank?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/memorable/version.rb
CHANGED
data/lib/memorable.rb
CHANGED
@@ -2,21 +2,27 @@ require 'active_support'
|
|
2
2
|
|
3
3
|
require 'memorable/version'
|
4
4
|
require 'memorable/error'
|
5
|
-
require 'memorable/
|
5
|
+
require 'memorable/registration'
|
6
6
|
require 'memorable/template_engine'
|
7
7
|
require 'memorable/model'
|
8
8
|
require 'memorable/controller'
|
9
9
|
|
10
10
|
module Memorable
|
11
|
+
@config = ActiveSupport::OrderedOptions.new
|
11
12
|
|
12
13
|
class << self
|
14
|
+
attr_reader :config
|
15
|
+
|
13
16
|
def setup(&block)
|
14
|
-
|
17
|
+
yield config if block_given?
|
18
|
+
|
19
|
+
config.journals_model.send :include, Memorable::Model
|
20
|
+
ActionController::Base.send :include, Memorable::Controller
|
15
21
|
|
16
|
-
|
17
|
-
|
22
|
+
config.default_templates_directory ||= File.dirname(__FILE__)
|
23
|
+
config.template_engine ||= DefaultYAMLEngine
|
18
24
|
|
19
|
-
|
25
|
+
config.template_engine.load!
|
20
26
|
end
|
21
27
|
end
|
22
28
|
end
|
data/memorable.gemspec
CHANGED
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Cxg"]
|
10
10
|
spec.email = ["xg.chen87@gmail.com"]
|
11
11
|
spec.summary = "A Rails logging system based on actions."
|
12
|
-
spec.description = %q{A Rails logging system based on actions,
|
13
|
-
callbacks. Customizable ready-to-run
|
14
|
-
and built-in I18n support.}
|
12
|
+
spec.description = %q{A Rails logging system based on actions, instead of
|
13
|
+
model callbacks. Customizable ready-to-run
|
14
|
+
configurations and built-in I18n support.}
|
15
15
|
spec.homepage = "https://github.com/serco-chen/memorable"
|
16
16
|
spec.license = "MIT"
|
17
17
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memorable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cxg
|
@@ -59,9 +59,9 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '10.0'
|
61
61
|
description: |-
|
62
|
-
A Rails logging system based on actions,
|
63
|
-
callbacks. Customizable ready-to-run
|
64
|
-
and built-in I18n support.
|
62
|
+
A Rails logging system based on actions, instead of
|
63
|
+
model callbacks. Customizable ready-to-run
|
64
|
+
configurations and built-in I18n support.
|
65
65
|
email:
|
66
66
|
- xg.chen87@gmail.com
|
67
67
|
executables: []
|
@@ -70,12 +70,14 @@ extra_rdoc_files: []
|
|
70
70
|
files:
|
71
71
|
- Gemfile
|
72
72
|
- LICENSE
|
73
|
+
- README.md
|
73
74
|
- lib/memorable.rb
|
74
|
-
- lib/memorable/configuration.rb
|
75
75
|
- lib/memorable/controller.rb
|
76
76
|
- lib/memorable/error.rb
|
77
77
|
- lib/memorable/model.rb
|
78
|
+
- lib/memorable/registration.rb
|
78
79
|
- lib/memorable/template_engine.rb
|
80
|
+
- lib/memorable/template_engines/default.rb
|
79
81
|
- lib/memorable/templates/en_US.yml
|
80
82
|
- lib/memorable/version.rb
|
81
83
|
- memorable.gemspec
|