memorable 0.1.2 → 0.1.3

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: f4605915b94644c1cf4eec46d551ea971637c61b
4
- data.tar.gz: 1d8e9deda6b5a1cb73dd82cd078d2bc108234a2f
3
+ metadata.gz: b1c1a0cf58461321fd1ebd8a9f3a651f867bb724
4
+ data.tar.gz: 0410ce862905268bc71994f35993b5c67d2afc97
5
5
  SHA512:
6
- metadata.gz: 017ee728f18ac91a52790617457d9910e6f9025a14ef2d75c34ecff817bc67dcb6ecf4ffca203b18dc85311d540643c65eb27dcc0749fc49197a58ec59b7a860
7
- data.tar.gz: 420b4c3b0b1cdc0482dbdbf7768c59911fc3b1f0de0f74d00b2f7dd2d6602ca96327e3db475815161ee01d67a452712968ccbdd8f831124b0865a2801a314142
6
+ metadata.gz: b9fdb08440094d599523551036dd01d97ac863de4b8463127bad6a253ef317fa0edfb9038fe130056009768f4195d42f4698b328447f99846250e498d1ab9797
7
+ data.tar.gz: bb705ce042ee5b337926b4e0c67f4062b2ff9cfb0e131f4289a168821462f9320e28bcbac8e8618b68e0ab2ed34a42feb53939aff70688db264f4e591f9d0fa1
data/README.md CHANGED
@@ -31,6 +31,23 @@ gem install memorable-<VERSION>.gem
31
31
 
32
32
  ## Configuration
33
33
 
34
+ run:
35
+
36
+ $ rails g memorable:install MODELNAME
37
+
38
+ or ('journal' is the default name if not given one)
39
+
40
+ $ rails g memorable:install
41
+
42
+ This command will create 4 files for you to start with:
43
+
44
+ 1. `db/migration/20150228032852_create_memorable_journal.rb`
45
+ 2. `app/models/journal.rb`
46
+ 3. `config/initializers/memorable.rb`
47
+ 4. `config/locales/memorable.en.yml`
48
+
49
+ Or you can manually setup as follows:
50
+
34
51
  ### Initializer
35
52
 
36
53
  Write these lines of code to your configuration file, for example, `memorable.rb`.
@@ -60,17 +77,13 @@ class CreateJournal < ActiveRecord::Migration
60
77
  t.integer :resource_id
61
78
  t.string :resource_type
62
79
  t.text :meta
80
+ t.text :content
63
81
 
64
82
  t.timestamps
65
83
  end
66
84
 
67
85
  add_index :journals, :user_id
68
86
  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
87
  end
75
88
 
76
89
  def down
@@ -78,9 +91,6 @@ class CreateJournal < ActiveRecord::Migration
78
91
  remove_index :journals, :resource_id
79
92
 
80
93
  drop_table :journals
81
-
82
- # If you are not using globalize, comment this line
83
- Journal.drop_translation_table!
84
94
  end
85
95
  end
86
96
  ```
@@ -97,12 +107,11 @@ Create a ActiveRecord Model, and you are all set.
97
107
 
98
108
  ```ruby
99
109
  class Journal < ActiveRecord::Base
100
- attr_accessible :resource_id, :resource_type, :user_id, :meta, :content
110
+ include Memorable::Model
101
111
 
102
- store :meta, accessors: [:controller, :action, :template_key ]
112
+ attr_accessible :resource_id, :resource_type, :user_id, :meta, :content
103
113
 
104
- # If you are not using globalize, comment this line
105
- translates :content, :fallbacks_for_empty_translations => true
114
+ store :meta
106
115
 
107
116
  belongs_to :user
108
117
  belongs_to :resource, polymorphic: true, :touch => true
@@ -111,30 +120,47 @@ end
111
120
 
112
121
  ## Usage
113
122
 
123
+ Specify which actions you would like to log:
124
+
125
+ ```ruby
126
+ class ContactsController < ApplicationController
127
+ memorize :only => [:create, :update]
128
+ end
129
+ ```
130
+
131
+ `memorize` method support following options:
132
+
133
+ ```
134
+ - only, except # It's used to specify action names to log
135
+ - resource_name # Use to detect resource in special case
136
+ - if, unless # Add condition wheter to log or not
137
+ ```
138
+
114
139
  Add your own templates using yaml, this gem ships with a default yml template engine.
115
140
 
116
- Put your templates under `app/views/memorable` directory of you project, and name them with something like `en_US.yml`
141
+ Put your templates under `config/locales` directory of you project, and name them with something like `memorable.en.yml`
117
142
 
118
143
  Here's an example of a typical template file
119
144
 
120
145
  ```
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}."
146
+ en:
147
+ memorable:
148
+ defaults:
149
+ create:
150
+ base: "%{resource_type} %{resource_id} created."
151
+ update:
152
+ base: "%{resource_type} %{resource_id} updated."
153
+ destroy:
154
+ base: "%{resource_type} %{resource_id} deleted."
155
+
156
+ contacts:
157
+ create:
158
+ base: "Added vendor %{name} to Vendor Library."
159
+ update:
160
+ base: "Edited information for Vendor %{name}."
161
+ name: "Change Vendor Name form %{previous_name} to %{name}."
162
+ destroy:
163
+ base: "Deleted Vendor %{name}."
138
164
  ```
139
165
 
140
166
  As you can see, controller_name and action_name are used as the first two levels of template_keys.
@@ -153,7 +179,7 @@ class ContactsController < ApplicationController
153
179
  private
154
180
 
155
181
  def memorable_update
156
- if @contact.previous_changes.key? [:name]
182
+ if @contact.previous_changes.key? :name
157
183
  {template_key: 'name', company_email: @contact.company.email}
158
184
  end
159
185
  end
@@ -0,0 +1,9 @@
1
+ en:
2
+ memorable:
3
+ defaults:
4
+ create:
5
+ base: "%{resource_type} %{resource_id} created."
6
+ update:
7
+ base: "%{resource_type} %{resource_id} updated."
8
+ destroy:
9
+ base: "%{resource_type} %{resource_id} deleted."
@@ -0,0 +1,29 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module ActiveRecord
4
+ module Generators
5
+ class MemorableGenerator < ActiveRecord::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ desc "Create a migration to create a table for logging. "
9
+
10
+ def generate_migration
11
+ migration_template "migration.rb.erb", "db/migrate/#{migration_file_name}"
12
+ end
13
+
14
+ protected
15
+
16
+ def migration_name
17
+ "create_memorable_#{table_name}"
18
+ end
19
+
20
+ def migration_file_name
21
+ "#{migration_name}.rb"
22
+ end
23
+
24
+ def migration_class_name
25
+ migration_name.camelize
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Memorable
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ desc "Creates a Memorable initializer and copy locale files to your application."
9
+
10
+ argument :model_name, :type => :string, :default => "journal",
11
+ :desc => "The name of logging model.",
12
+ :banner => "Logging model name, eg: journal"
13
+
14
+ def invoke_migration_generator
15
+ generate "active_record:memorable #{model_name.pluralize}"
16
+ end
17
+
18
+ def copy_model_file
19
+ template "model.rb.erb", "app/models/#{model_name}.rb"
20
+ end
21
+
22
+ def copy_initializer
23
+ template "memorable.rb.erb", "config/initializers/memorable.rb"
24
+ end
25
+
26
+ def copy_locale
27
+ copy_file "../../../config/locales/en.yml", "config/locales/memorable.en.yml"
28
+ end
29
+
30
+ # def show_readme
31
+ # readme "README" if behavior == :invoke
32
+ # end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+ Memorable.setup do |config|
2
+ config.journals_model = <%= model_name.capitalize %>
3
+
4
+ # Specify template engine, default
5
+ # config.template_engine = DefaultYAMLEngine
6
+ end
@@ -0,0 +1,23 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+ def up
3
+ create_table :<%= table_name %> do |t|
4
+ t.integer :user_id
5
+ t.integer :resource_id
6
+ t.string :resource_type
7
+ t.text :meta
8
+ t.text :content
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :<%= table_name %>, :user_id
14
+ add_index :<%= table_name %>, :resource_id
15
+ end
16
+
17
+ def down
18
+ remove_index :<%= table_name %>, :user_id
19
+ remove_index :<%= table_name %>, :resource_id
20
+
21
+ drop_table :<%= table_name %>
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ class <%= model_name.capitalize %> < ActiveRecord::Base
2
+ include Memorable::Model
3
+
4
+ attr_accessible :resource_id, :resource_type, :user_id, :meta, :content
5
+
6
+ store :meta
7
+
8
+ belongs_to :user
9
+ belongs_to :resource, polymorphic: true, :touch => true
10
+ end
data/lib/memorable.rb CHANGED
@@ -15,14 +15,9 @@ module Memorable
15
15
 
16
16
  def setup(&block)
17
17
  yield config if block_given?
18
-
19
- config.journals_model.send :include, Memorable::Model
20
18
  ActionController::Base.send :include, Memorable::Controller
21
19
 
22
- config.default_templates_directory ||= File.dirname(__FILE__)
23
- config.template_engine ||= DefaultYAMLEngine
24
-
25
- config.template_engine.load!
20
+ config.template_engine ||= DefaultYAMLEngine
26
21
  end
27
22
  end
28
23
  end
@@ -3,7 +3,11 @@ module Memorable
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- append_after_filter :memorize_callback
6
+ if Rails::VERSION::MAJOR > 3
7
+ append_after_action :memorize_callback
8
+ else
9
+ append_after_filter :memorize_callback
10
+ end
7
11
  end
8
12
 
9
13
  private
@@ -12,10 +16,10 @@ module Memorable
12
16
  return unless memorable?
13
17
 
14
18
  # prepare locals for action
15
- locals = extract_memorable_locals
19
+ options = extract_memorable_options
16
20
 
17
21
  # write to database
18
- Memorable.config.journals_model.create_with_options!(locals)
22
+ Memorable.config.journals_model.create_with_params!(options)
19
23
 
20
24
  rescue Exception => e
21
25
  raise e if Rails.env.development? # for debug
@@ -28,30 +32,35 @@ module Memorable
28
32
  response.successful?
29
33
  end
30
34
 
31
- def extract_memorable_locals
32
- locals = ActiveSupport::HashWithIndifferentAccess.new ({
33
- controller: controller_name,
34
- action: action_name,
35
- user_id: current_user.id
35
+ def extract_memorable_options
36
+ options = ActiveSupport::HashWithIndifferentAccess.new ({
37
+ user_id: current_user.try(:id),
38
+ meta: {
39
+ controller: controller_name,
40
+ action: action_name
41
+ }
36
42
  })
37
43
 
38
44
  if memorable_resource
39
- locals.merge! Hash[memorable_resource.previous_changes.map {|key, value| ["previous_#{key}", value[0]]}]
40
- locals.merge! memorable_resource.attributes
41
- locals.merge!({
45
+ resource_previous = Hash[memorable_resource.previous_changes.map {|key, value| ["previous_#{key}", value[0]]}]
46
+ resource_attributes = memorable_resource.attributes
47
+ resource_options = {
42
48
  resource_id: memorable_resource.id,
43
49
  resource_type: memorable_resource.class.to_s
44
- })
50
+ }
51
+
52
+ options[:meta].merge!(resource_previous).merge!(resource_attributes).merge!(resource_options)
53
+ options.merge!(resource_options)
45
54
  end
46
55
 
47
56
  custom_method_name = "memorable_#{action_name}"
48
57
 
49
58
  if respond_to? custom_method_name, true
50
59
  custom_locals = self.send custom_method_name
51
- locals.merge!(custom_locals) if custom_locals.is_a?(Hash)
60
+ options[:meta].merge!(custom_locals) if custom_locals.is_a?(Hash)
52
61
  end
53
62
 
54
- locals
63
+ options
55
64
  end
56
65
 
57
66
  def memorable_resource
@@ -3,33 +3,33 @@ module Memorable
3
3
  module Model
4
4
  extend ActiveSupport::Concern
5
5
 
6
- def write_content(options)
7
- current_locale = I18n.locale
6
+ def write_content(locals)
7
+ self.content = memorable_content(locals)
8
+ end
8
9
 
9
- Memorable.config.template_engine.assemble(options).each do |template|
10
- I18n.locale = template[0]
11
- self.content = template[1]
12
- end
10
+ private
13
11
 
14
- I18n.locale = current_locale
12
+ def memorable_content(*args)
13
+ Memorable.config.template_engine.run(*args)
15
14
  end
16
15
 
17
16
  module ClassMethods
18
- def create_with_options!(options={})
19
- journal = self.build_with_options(options)
20
- journal.save!
17
+ def create_with_params!(params={})
18
+ instance = self.build_with_params(params)
19
+ instance.save!
21
20
  end
22
21
 
23
- def build_with_options(options)
24
- journal = self.new
22
+ def build_with_params(params)
23
+ instance = self.new
25
24
 
26
- journal.user_id = options.delete :user_id
27
- journal.resource_id = options.delete :resource_id
28
- journal.resource_type = options.delete :resource_type
29
- journal.meta = options if journal.respond_to?(:meta)
25
+ # set attributes and meta data if possible
26
+ params.each do |key, value|
27
+ instance.send "#{key}=", value if instance.respond_to?(key)
28
+ end
30
29
 
31
- journal.write_content(options)
32
- journal
30
+ # render content with meta data
31
+ instance.write_content(params[:meta])
32
+ instance
33
33
  end
34
34
  end
35
35
  end
@@ -1,42 +1,17 @@
1
- require 'singleton'
2
-
3
1
  module Memorable
4
2
 
5
3
  # This is an abstract class, do not use it directly. Inherit from this class
6
- # and implement custom load!/parse/render medthods.
4
+ # and implement custom render medthods.
7
5
  class TemplateEngine
8
- include Singleton
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
- #
23
- attr_reader :load_path, :templates
24
6
 
25
- def initialize
26
- @load_path = []
27
- @templates = {}
28
- end
29
-
30
- def assemble(options)
31
- parse(options[:controller], options[:action], options[:template_key]).map do |locale, template|
32
- content = render(template, options)
33
- [locale, content]
34
- end
7
+ def self.run(*args)
8
+ self.new.render(*args)
35
9
  end
36
10
 
37
11
  # Override this method in subclass
38
- def parse(controller, action, sub_key)
12
+ def render(*args)
39
13
  end
14
+
40
15
  end
41
16
  end
42
17
 
@@ -1,79 +1,19 @@
1
- require 'yaml'
2
-
3
1
  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
2
 
52
- def render(template, locals)
53
- if locals
54
- I18n.interpolate(template, locals)
55
- else
56
- template
57
- end
58
- end
59
-
60
- private
3
+ # This is the default engine, which uses I18n to find the template and
4
+ # to interpolate variables.
5
+ class DefaultYAMLEngine < TemplateEngine
61
6
 
62
- # Loads a YAML template file.
63
- def load_yml(filename)
7
+ def render(locals)
8
+ controller, action, sub_key = locals[:controller], locals[:action], locals[:template_key] || 'base'
9
+ @key ||= "memorable.#{controller}.#{action}.#{sub_key}"
64
10
  begin
65
- YAML.load_file(filename)
66
- rescue TypeError, ScriptError, StandardError => e
67
- raise InvalidYAMLData.new(filename, e.inspect)
11
+ I18n.t! @key, locals
12
+ rescue I18n::MissingTranslationData => e
13
+ raise e if @key.start_with?("memorable.defaults")
14
+ @key = "memorable.defaults.#{action}.#{sub_key}"
15
+ retry
68
16
  end
69
17
  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
18
  end
79
19
  end
@@ -1,3 +1,3 @@
1
1
  module Memorable
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
data/memorable.gemspec CHANGED
@@ -1,12 +1,11 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
2
+ $:.push File.expand_path("../lib", __FILE__)
4
3
  require 'memorable/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = "memorable"
8
7
  spec.version = Memorable::VERSION
9
- spec.authors = ["Cxg"]
8
+ spec.authors = ["Xiaoguang Chen"]
10
9
  spec.email = ["xg.chen87@gmail.com"]
11
10
  spec.summary = "A Rails logging system based on actions."
12
11
  spec.description = %q{A Rails logging system based on actions, instead of
@@ -19,6 +18,7 @@ Gem::Specification.new do |spec|
19
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
20
  spec.require_paths = ["lib"]
21
+ spec.required_ruby_version = '>= 1.9.3'
22
22
 
23
23
  spec.add_dependency 'activesupport', '>= 3.2.8', "< 5.0"
24
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memorable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
- - Cxg
7
+ - Xiaoguang Chen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-26 00:00:00.000000000 Z
11
+ date: 2015-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -71,6 +71,12 @@ files:
71
71
  - Gemfile
72
72
  - LICENSE
73
73
  - README.md
74
+ - config/locales/en.yml
75
+ - lib/generators/active_record/memorable_generator.rb
76
+ - lib/generators/memorable/install_generator.rb
77
+ - lib/generators/templates/memorable.rb.erb
78
+ - lib/generators/templates/migration.rb.erb
79
+ - lib/generators/templates/model.rb.erb
74
80
  - lib/memorable.rb
75
81
  - lib/memorable/controller.rb
76
82
  - lib/memorable/error.rb
@@ -78,7 +84,6 @@ files:
78
84
  - lib/memorable/registration.rb
79
85
  - lib/memorable/template_engine.rb
80
86
  - lib/memorable/template_engines/default.rb
81
- - lib/memorable/templates/en_US.yml
82
87
  - lib/memorable/version.rb
83
88
  - memorable.gemspec
84
89
  homepage: https://github.com/serco-chen/memorable
@@ -93,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
93
98
  requirements:
94
99
  - - ">="
95
100
  - !ruby/object:Gem::Version
96
- version: '0'
101
+ version: 1.9.3
97
102
  required_rubygems_version: !ruby/object:Gem::Requirement
98
103
  requirements:
99
104
  - - ">="
@@ -1,9 +0,0 @@
1
- defaults:
2
- create:
3
- base: "%{resource_type} created."
4
- update:
5
- base: "%{resource_type} updated."
6
- destroy:
7
- base: "%{resource_type} deleted."
8
- others:
9
- base: "%{action} was executed on %{resource_type}."