memorable 0.1.1 → 0.1.2
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.
- 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
|