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 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