memorable 0.1.2 → 0.1.3

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: 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}."