chrno_audit 0.2.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e0062dcbf09cede00ed1653833974379aec8b57d
4
+ data.tar.gz: 04895bc6278aec3259ed18d9612ddcb53a9d9e06
5
+ SHA512:
6
+ metadata.gz: e54826cdb9a5a549873c544f9325cbdb751ae9cfc8bd5b1ffb7cc9215ab6c0c6eab03fae334b5162981706b67067a0b42400ac8058fb8c7a7e8491761d0ba40f
7
+ data.tar.gz: 4a1c88092ac240d6052b201ef3ed7d0c3bfefdf63b08dde907f16e67210627f200e30ee09a5bc8ed0ec664037d2b5ed1a2f29ee0a8b77a6f0df0e190d3c8f764
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,92 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ chrno_audit (0.2.4)
5
+ activerecord (>= 3.1)
6
+ rails (>= 3.1)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionmailer (3.2.13)
12
+ actionpack (= 3.2.13)
13
+ mail (~> 2.5.3)
14
+ actionpack (3.2.13)
15
+ activemodel (= 3.2.13)
16
+ activesupport (= 3.2.13)
17
+ builder (~> 3.0.0)
18
+ erubis (~> 2.7.0)
19
+ journey (~> 1.0.4)
20
+ rack (~> 1.4.5)
21
+ rack-cache (~> 1.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.2.1)
24
+ activemodel (3.2.13)
25
+ activesupport (= 3.2.13)
26
+ builder (~> 3.0.0)
27
+ activerecord (3.2.13)
28
+ activemodel (= 3.2.13)
29
+ activesupport (= 3.2.13)
30
+ arel (~> 3.0.2)
31
+ tzinfo (~> 0.3.29)
32
+ activeresource (3.2.13)
33
+ activemodel (= 3.2.13)
34
+ activesupport (= 3.2.13)
35
+ activesupport (3.2.13)
36
+ i18n (= 0.6.1)
37
+ multi_json (~> 1.0)
38
+ arel (3.0.3)
39
+ builder (3.0.4)
40
+ erubis (2.7.0)
41
+ hike (1.2.3)
42
+ i18n (0.6.1)
43
+ journey (1.0.4)
44
+ json (1.8.1)
45
+ mail (2.5.4)
46
+ mime-types (~> 1.16)
47
+ treetop (~> 1.4.8)
48
+ mime-types (1.25.1)
49
+ multi_json (1.10.1)
50
+ polyglot (0.3.5)
51
+ rack (1.4.5)
52
+ rack-cache (1.2)
53
+ rack (>= 0.4)
54
+ rack-ssl (1.3.4)
55
+ rack
56
+ rack-test (0.6.2)
57
+ rack (>= 1.0)
58
+ rails (3.2.13)
59
+ actionmailer (= 3.2.13)
60
+ actionpack (= 3.2.13)
61
+ activerecord (= 3.2.13)
62
+ activeresource (= 3.2.13)
63
+ activesupport (= 3.2.13)
64
+ bundler (~> 1.0)
65
+ railties (= 3.2.13)
66
+ railties (3.2.13)
67
+ actionpack (= 3.2.13)
68
+ activesupport (= 3.2.13)
69
+ rack-ssl (~> 1.3.2)
70
+ rake (>= 0.8.7)
71
+ rdoc (~> 3.4)
72
+ thor (>= 0.14.6, < 2.0)
73
+ rake (10.4.2)
74
+ rdoc (3.12.2)
75
+ json (~> 1.4)
76
+ sprockets (2.2.3)
77
+ hike (~> 1.2)
78
+ multi_json (~> 1.0)
79
+ rack (~> 1.0)
80
+ tilt (~> 1.1, != 1.3.0)
81
+ thor (0.19.1)
82
+ tilt (1.4.1)
83
+ treetop (1.4.15)
84
+ polyglot
85
+ polyglot (>= 0.3.1)
86
+ tzinfo (0.3.42)
87
+
88
+ PLATFORMS
89
+ ruby
90
+
91
+ DEPENDENCIES
92
+ chrno_audit!
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Denis Diachkov aka chrno
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # chrno_audit
2
+
3
+ Простейшая реализация аудита для ActiveRecord.
4
+
5
+ ## Установка
6
+
7
+ Добавьте в Gemfile:
8
+
9
+ ```ruby
10
+ gem "chrno_audit"
11
+ ```
12
+
13
+ и запустите `bundle install`. Затем нужно будет сгенерировать необходимые для работы файлы и создать таблицы в БД:
14
+
15
+ ```console
16
+ rails g chrno_audit:install
17
+ rake db:migrate
18
+ ```
19
+
20
+ Помните, что необходимо перезапустить приложение, если оно уже запущено.
21
+
22
+ ## Пример использования
23
+
24
+ ### Модель
25
+
26
+ После установки джема в моделях становится доступен метод `audit( *params )`, подключающий модель к системе аудита. В качестве параметров методу audit можно передавать список полей для аудита (по умолчанию все), например:
27
+
28
+ ```ruby
29
+ class Page < ActiveRecord::Base
30
+ audit :text, :subject
31
+ end
32
+ ```
33
+
34
+ Можно использовать псевдо-поле :all, если необходим аудит всех полей:
35
+
36
+ ```ruby
37
+ class Page < ActiveRecord::Base
38
+ audit :all
39
+ end
40
+ ```
41
+
42
+ Можно указывать список полей, которые необходимо игнорировать при аудите:
43
+
44
+ ```ruby
45
+ class Page < ActiveRecord::Base
46
+ audit :all, :except => [ :author ]
47
+ end
48
+ ```
49
+
50
+ Можно указать список действий для аудита (create, update, destroy):
51
+
52
+ ```ruby
53
+ class Page < ActiveRecord::Base
54
+ audit :all, :when => [ :create ]
55
+ end
56
+ ```
57
+
58
+ ### Контроллер
59
+
60
+ После установки джема в контроллерах становятся доступны следующие методы:
61
+ * `audit_context( proc_or_symbol = nil, &block )`: задаёт контекст аудита;
62
+ * `create_audit_record!( context = {}, initiator = nil )`: создаёт запись в логе для текущего экшена;
63
+
64
+ Cохраняем в контексте текущего пользователя и его IP:
65
+
66
+ ```ruby
67
+ class ApplicationController < ActionController::Base
68
+ audit_context -> {{ ip: request.remote_addr, current_user: current_user }}
69
+ end
70
+ ```
71
+
72
+ _NB:_ блок исполняется в контексте контроллера и обязан возврашать хеш!
73
+
74
+ Используем метод для генерации контекста:
75
+
76
+ ```ruby
77
+ class ApplicationController < ActionController::Base
78
+ audit_context :generate_context
79
+
80
+ def generate_context
81
+ { ip: request.remote_addr }
82
+ end
83
+ end
84
+
85
+ class MyController < ApplicationController
86
+ def generate_context
87
+ super.merge { foo: "bar" }
88
+ end
89
+ end
90
+ ```
91
+
92
+ Генерируем запись в аудит-логе:
93
+
94
+ ```ruby
95
+ ...
96
+ def some_action
97
+ create_audit_record!({ foo: "bar" }, current_user )
98
+ end
99
+ ...
100
+ ```
101
+
102
+ В качестве `auditable_type` будет использовано имя контроллера, а в качестве `action` — имя экшена ("some_action").
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ 1) pagination
2
+ 2) написать в README про resources :plural_name do chrno_audit end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Обзервер записывает изменения моделей в лог.
5
+ #
6
+ class ChrnoAudit::AuditObserver < ActiveRecord::Observer
7
+ # По умолчанию ничего не обозреваем
8
+ def self.observed_classes
9
+ []
10
+ end
11
+
12
+ ##
13
+ # Добавляет обзервер к заданной модели.
14
+ # @param [Class] model модель
15
+ #
16
+ def self.attach( model )
17
+ self.instance.send :add_observer!, model
18
+ end
19
+
20
+ # Создаёт запись о создании сущности.
21
+ def after_create( entity )
22
+ create_audit_record! entity, :create
23
+ end
24
+
25
+ # Создаёт запись об изменении сущности.
26
+ def after_update( entity )
27
+ create_audit_record! entity, :update
28
+ end
29
+
30
+ # Создаёт запись об удалении сущности.
31
+ def after_destroy( entity )
32
+ create_audit_record! entity, :destroy
33
+ end
34
+
35
+ private
36
+
37
+ ##
38
+ # Создаёт запись в логе.
39
+ #
40
+ # @param [ActiveRecord::Base] entity
41
+ # @param [#to_s] action
42
+ #
43
+ def create_audit_record!( entity, action )
44
+ # Ничего не делаем, если аудит данного действия отключён
45
+ return unless entity.class.auditable_actions.include? action
46
+
47
+ # Получаем изменения и контекст
48
+ changes_to_store = get_changes( entity )
49
+ context = get_context.with_indifferent_access
50
+
51
+ # Ничего не делаем если модель не изменилась
52
+ return if entity.class.auditable_options[ :ignore_empty_diff ] && changes_to_store.empty? && action != :destroy
53
+
54
+ ChrnoAudit::AuditRecord.create do |record|
55
+ record.action = action.to_s
56
+ record.auditable = entity
57
+ record.diff = changes_to_store
58
+ record.initiator = context.delete( :initiator ) || context.delete( :current_user )
59
+ record.context = context
60
+ end
61
+ end
62
+
63
+ ##
64
+ # Формирует массив изменений для заданной записи.
65
+ # @param [ActiveRecord::Base] entity
66
+ # @return [Hash]
67
+ #
68
+ def get_changes( entity )
69
+ entity.changes.select { |field| entity.class.auditable_fields.include? field }
70
+ end
71
+
72
+ ##
73
+ # Возвращает текущий контекст для аудита.
74
+ # @return [Hash]
75
+ #
76
+ def get_context
77
+ ( Thread.current[ :audit_context ].respond_to?( :call ) ? Thread.current[ :audit_context ].call : {} ).tap do |context|
78
+ # Проверяем, что контекст это хеш
79
+ raise "Invalid audit context: Hash expected, got: #{context.inspect}" if context && !context.is_a?( Hash )
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Сущность "запись лога".
5
+ #
6
+ class ChrnoAudit::AuditRecord < ActiveRecord::Base
7
+ # Имя таблицы с логами
8
+ self.table_name = ChrnoAudit.config.table_name || "audit_log"
9
+
10
+ # Кто изменил?
11
+ belongs_to :initiator, :polymorphic => true
12
+
13
+ # Что изменил?
14
+ belongs_to :auditable, :polymorphic => true
15
+
16
+ # Изменения
17
+ serialize :diff, ChrnoAudit.config.serializer || Object
18
+
19
+ # Контекст
20
+ serialize :context, ChrnoAudit.config.serializer || Object
21
+
22
+ # Возвращает записи для заданного типа сущности.
23
+ scope :for_type, -> *types { where( auditable_type: types.map { |t| t.class.model_name })}
24
+
25
+ # Возвращает записи для заданных моделей.
26
+ scope :for_object, -> *records {
27
+ t = self.arel_table
28
+
29
+ # Логи для заданных записей
30
+ conditions = records.compact.map do |record|
31
+ t.where( t[ :auditable_type ].eq( record.class.model_name.to_s )) \
32
+ .where( t[ :auditable_id ].eq( record.id )) \
33
+ .project( t[ :id ] )
34
+ end
35
+
36
+ # Джойним результаты с помощью UNION ALL
37
+ query = conditions.inject { |c1, c2| c1.union( :all, c2 ) }
38
+
39
+ # Результирующий запрос
40
+ where( t[ :id ].in query )
41
+ }
42
+
43
+ # Возвращает записи заданного типа.
44
+ scope :with_action, -> action { where( action: action ) }
45
+ end
Binary file
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path( "../lib", __FILE__ )
3
+ require "chrno_audit/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "chrno_audit"
7
+ s.version = ChrnoAudit::VERSION
8
+ s.authors = [ "Denis Diachkov" ]
9
+ s.email = [ "d.diachkov@gmail.com" ]
10
+ s.homepage = "https://github.com/ddiachkov/chrno_audit"
11
+ s.summary = "Simple ActiveRecord audit system"
12
+
13
+ s.files = Dir[ "*", "app/**/*", "lib/**/*" ]
14
+ s.require_paths = [ "lib" ]
15
+
16
+ s.required_ruby_version = ">= 1.9.3"
17
+
18
+ s.add_runtime_dependency "rails", ">= 3.1"
19
+ s.add_runtime_dependency "activerecord", ">= 3.1"
20
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+ module ChrnoAudit
3
+ ##
4
+ # Расширение для ActionController.
5
+ #
6
+ module ActionControllerConcern
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ ##
11
+ # Хелпер для установки контекста аудита.
12
+ #
13
+ # @param [Proc, Symbol] proc_or_symbol
14
+ # символ или Proc для генерации контента (также может быть задано в виде блока)
15
+ #
16
+ # @example
17
+ # audit_context -> {{ ip: request.remote_addr }}
18
+ #
19
+ def audit_context( proc_or_symbol = nil, &block )
20
+ # Получаем Proc для генерации контекста
21
+ context_generator =
22
+ # Если задан блок -- используем его
23
+ if block_given?
24
+ block
25
+
26
+ # Если указан символ, то вызываем соответствующий метод
27
+ elsif proc_or_symbol.is_a? Symbol
28
+ Proc.new { self.send proc_or_symbol }
29
+
30
+ # Если указан Proc -- используем его
31
+ elsif proc_or_symbol.is_a? Proc
32
+ proc_or_symbol
33
+
34
+ else
35
+ raise ArgumentError, "Proc or Symbol expected, got: #{proc_or_symbol.inspect}"
36
+ end
37
+
38
+ before_filter do |controller|
39
+ # NB: согласно документации Ruby в Thread.current хранятся per-fiber атрибуты!
40
+ Thread.current[ :audit_context ] = Proc.new { controller.instance_exec( &context_generator ) }
41
+ end
42
+ end
43
+ end
44
+
45
+ ##
46
+ # Хелпер для создания записи аудита из контроллера.
47
+ # В качестве типа будет использовано имя текущего контоллера, в качестве действия -- текущий экшен.
48
+ #
49
+ # @param [Hash] context контекст
50
+ # @param [ActiveRecord::Base] initiator инициатор обновления
51
+ # @yield [ChrnoAudit::AuditRecord]
52
+ #
53
+ def create_audit_record!( context = {}, initiator = nil, &block )
54
+ ChrnoAudit::AuditRecord.create! do |record|
55
+ record.auditable_type = self.class.name
56
+ record.action = request.symbolized_path_parameters[ :action ]
57
+ record.initiator = initiator
58
+ record.context = context
59
+
60
+ # Даём возможность переопределить параметры
61
+ block.call( record ) if block
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,79 @@
1
+ # encoding: utf-8
2
+ module ChrnoAudit
3
+ ##
4
+ # Расширение для ActiveRecord.
5
+ #
6
+ module ActiveRecordConcern
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ ##
11
+ # Макрос добавляет в модель аудит изменений.
12
+ #
13
+ # @param [Symbol] fields
14
+ # список полей для аудита (по умолчанию все поля). Можно использовать
15
+ # псевдо-поле :all если необходим аудит всех полей.
16
+ #
17
+ # @param [Hash] options параметры аудита
18
+ # @option options [Array] :except ([])
19
+ # список полей, которые необходимо игнорировать при аудите (применяется
20
+ # совместно с :all)
21
+ #
22
+ # @option options [Array] :when ([ :create, :update, :destroy ])
23
+ # список действий над моделью (создание, изменение, удаление), при
24
+ # которых необходим аудит
25
+ #
26
+ # @option [true, false] :ignore_empty_diff (true)
27
+ # флаг: не записывать данные в базу, если аудируемые поля не изменились
28
+ #
29
+ # @example
30
+ # audit :all, :except => :foo
31
+ #
32
+ def audit( *fields )
33
+ # Если таблицы ещё нет, ничего не делаем (полезно для миграций)
34
+ unless table_exists?
35
+ Rails.logger.warn "Audit: try to audit model [#{name}] with non-existent table"
36
+ return
37
+ end
38
+
39
+ # Добавляем связь
40
+ has_many :audit_records, :as => :auditable, :class_name => "ChrnoAudit::AuditRecord"
41
+
42
+ # Добавляем обсервер
43
+ ChrnoAudit::AuditObserver.attach( self )
44
+
45
+ # Добавляем необходимые параметры
46
+ cattr_accessor :auditable_fields, :auditable_actions, :auditable_options
47
+
48
+ options = fields.extract_options!
49
+
50
+ # Настройки по умолчанию
51
+ options.reverse_merge! \
52
+ :except => [],
53
+ :when => [ :create, :update, :destroy ],
54
+ :ignore_empty_diff => true
55
+
56
+ # Нормализуем параметры
57
+ options[ :except ] = Array.wrap( options[ :except ] ).map( &:to_s )
58
+ options[ :when ] = Array.wrap( options[ :when ] ).map( &:to_sym )
59
+
60
+ # Получаем список полей.
61
+ self.auditable_fields =
62
+ # Аудит на всех полях?
63
+ if fields.count == 1 and fields.first == :all
64
+ # Всегда выкидываем timestamp и id.
65
+ column_names - %W{ id created_at updated_at } - options[ :except ]
66
+ else
67
+ ( fields - options.delete( :except )).map( &:to_s )
68
+ end
69
+
70
+ self.auditable_actions = options.delete( :when )
71
+ self.auditable_options = options
72
+
73
+ # Проверки
74
+ Rails.logger.warn "Audit: no fields to audit" if self.auditable_fields.empty?
75
+ Rails.logger.warn "Audit: no actions to audit" if self.auditable_actions.empty?
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ module ChrnoAudit
3
+ # Версия гема
4
+ VERSION = "0.2.4"
5
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ if Rails.version.to_i >= 4
3
+ # В четвёртых рельсах обзерверы вынесены в джем
4
+ gem "rails-observers", "~> 0.1.1"
5
+ require "rails-observers"
6
+
7
+ # Хак для eager load: по умолчанию класс ActiveRecord::Observer грузится ПОСЛЕ
8
+ # того грузятся модели из app/models при eager_load = true, что приводит к ошибке
9
+ # если рядом с моделями лежат обзервере. Поэтому грузим определение класса сразу.
10
+ require "rails/observers/activerecord/active_record"
11
+ end
12
+
13
+ require "active_support/configurable"
14
+ require "chrno_audit/version"
15
+
16
+ module ChrnoAudit
17
+ include ActiveSupport::Configurable
18
+
19
+ class Engine < Rails::Engine
20
+ initializer "chrno_audit.initialize", :before => :load_active_support do
21
+ require "chrno_audit/action_controller_concern"
22
+ require "chrno_audit/active_record_concern"
23
+
24
+ ActiveSupport.on_load( :action_controller ) do
25
+ include ChrnoAudit::ActionControllerConcern
26
+ end
27
+
28
+ ActiveSupport.on_load( :active_record ) do
29
+ include ChrnoAudit::ActiveRecordConcern
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ require "rails/generators"
3
+ require "rails/generators/migration"
4
+ require "active_record"
5
+
6
+ # Генератор создаёт миграцию и файл инициализации
7
+ module ChrnoAudit
8
+ class InstallGenerator < Rails::Generators::Base
9
+ source_root File.expand_path( "../templates", __FILE__ )
10
+ desc "installs migration and initializer"
11
+
12
+ def make_migration
13
+ migration_template "migration.rb", "db/migrate/create_audit_log"
14
+ end
15
+
16
+ def make_initializer
17
+ copy_file "initializer.rb", "config/initializers/chrno_audit.rb"
18
+ end
19
+
20
+ def show_readme
21
+ readme "README"
22
+ end
23
+
24
+ private
25
+
26
+ include Rails::Generators::Migration
27
+
28
+ # Код взят из генератора моделей
29
+ def self.next_migration_number(dirname)
30
+ next_migration_number = current_migration_number(dirname) + 1
31
+
32
+ if ActiveRecord::Base.timestamped_migrations
33
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
34
+ else
35
+ "%.3d" % next_migration_number
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+
2
+ ============================================================================
3
+
4
+ Ура! Всё готово! Осталось только добавить немного кода.
5
+
6
+ Вот пример кода, который может использоваться в контроллере:
7
+
8
+ def history$
9
+ @page = Page.find params[:id]
10
+ @history = ChrnoAudit::AuditRecord.for_object( @page ).order( "created_at DESC" )
11
+ end
12
+
13
+ Чтобы подключить модель к системе аудита эту строку необходимо добавить в файл модели:
14
+
15
+ audit :all
16
+
17
+ Have fun!
18
+ https://github.com/Undev/chrno_audit/tree/docs#Пример-использования
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ ChrnoAudit.configure do |config|
3
+ # Имя таблицы с событиями
4
+ # config.table_name = "audit_log"
5
+
6
+ # Кодер для сериализации diff'а
7
+ # config.serializer = ActiveRecord::Coders::YAMLColumn
8
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ class CreateAuditLog < ActiveRecord::Migration
3
+ def change
4
+ create_table :audit_log do |t|
5
+ t.string :auditable_type, :null => false
6
+ t.integer :auditable_id
7
+ t.string :initiator_type
8
+ t.integer :initiator_id
9
+ t.string :action, :null => false
10
+ t.text :diff
11
+ t.text :context
12
+ t.datetime :created_at, :null => false
13
+ end
14
+
15
+ add_index :audit_log, [ :auditable_type, :auditable_id ]
16
+ add_index :audit_log, [ :initiator_type, :initiator_id ]
17
+ add_index :audit_log, :action
18
+ add_index :audit_log, :created_at, :order => { :created_at => :desc }
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chrno_audit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.4
5
+ platform: ruby
6
+ authors:
7
+ - Denis Diachkov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ description:
42
+ email:
43
+ - d.diachkov@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Gemfile
49
+ - Gemfile.lock
50
+ - MIT-LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - TODO
54
+ - app/models/chrno_audit/audit_observer.rb
55
+ - app/models/chrno_audit/audit_record.rb
56
+ - chrno_audit-0.4.0.gem
57
+ - chrno_audit.gemspec
58
+ - lib/chrno_audit.rb
59
+ - lib/chrno_audit/action_controller_concern.rb
60
+ - lib/chrno_audit/active_record_concern.rb
61
+ - lib/chrno_audit/version.rb
62
+ - lib/generators/chrno_audit/install_generator.rb
63
+ - lib/generators/chrno_audit/templates/README
64
+ - lib/generators/chrno_audit/templates/initializer.rb
65
+ - lib/generators/chrno_audit/templates/migration.rb
66
+ homepage: https://github.com/ddiachkov/chrno_audit
67
+ licenses: []
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 1.9.3
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.4.8
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Simple ActiveRecord audit system
89
+ test_files: []
90
+ has_rdoc: