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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7fb95cbd8bfc993b815802ff41abe3abf913f4f
4
- data.tar.gz: 52fe4c06f792b75c26a461057ceb477b206ee30d
3
+ metadata.gz: f4605915b94644c1cf4eec46d551ea971637c61b
4
+ data.tar.gz: 1d8e9deda6b5a1cb73dd82cd078d2bc108234a2f
5
5
  SHA512:
6
- metadata.gz: 746e7e131f7f1cd71c11e53a19ae00bc7e26eeb467af2026a59c400554555129d06c7a1fe765c5249264d2c688299d825eae0226e69ec809d02b52fac878f61e
7
- data.tar.gz: 3a728d5a5021dee59581388cbd8493c554e95db98b86ce73c68906d1f222b3dc21b884f7f6d463537c71194f6ac66ffabd84d0e61ca8679487899190e5418267
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
+ ```
@@ -15,7 +15,7 @@ module Memorable
15
15
  locals = extract_memorable_locals
16
16
 
17
17
  # write to database
18
- Configuration.journals_model.create_with_options!(locals)
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
- Configuration.registered?(controller_name, action_name) &&
27
- Configuration.condition_matched?(self) &&
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
- Configuration.resource_name(controller_name) || controller_name.singularize
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
- Configuration.register action_names, controller_name, options, condition_proc
98
+ Registration.register action_names, controller_name, options, condition_proc
104
99
  end
105
100
 
106
101
  def all_actions
@@ -6,9 +6,9 @@ module Memorable
6
6
  def write_content(options)
7
7
  current_locale = I18n.locale
8
8
 
9
- TemplateEngine.assemble(options).each do |template|
10
- I18n.locale = template[0]
11
- content = template[1]
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 Configuration
2
+ class Registration
3
3
  @register_actions = {}
4
- @journals_model = nil
5
4
 
6
5
  class << self
7
- attr_reader :register_actions, :journals_model
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
- action_templates(options[:controller], options[:action], options[:template_key]).map do |locale, template|
35
- content = render_template(template, options)
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
- protected
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
@@ -1,3 +1,3 @@
1
1
  module Memorable
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
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/configuration'
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
- Configuration.class_eval(&block) if block_given?
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
- Configuration.journals_model.send :include, Memorable::Model
17
- ActionController::Base.send :include, Memorable::Controller
22
+ config.default_templates_directory ||= File.dirname(__FILE__)
23
+ config.template_engine ||= DefaultYAMLEngine
18
24
 
19
- TemplateEngine.load!
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, not model
13
- callbacks. Customizable ready-to-run configurations
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.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, not model
63
- callbacks. Customizable ready-to-run configurations
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