action_audit 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +66 -0
- data/Rakefile +1 -0
- data/action_audit.gemspec +26 -0
- data/lib/action_audit.rb +34 -0
- data/lib/action_audit/ar.rb +44 -0
- data/lib/action_audit/controller_concern.rb +25 -0
- data/lib/action_audit/event_processor.rb +31 -0
- data/lib/action_audit/factory.rb +31 -0
- data/lib/action_audit/log_store.rb +19 -0
- data/lib/action_audit/resque_concern.rb +21 -0
- data/lib/action_audit/version.rb +3 -0
- data/spec/action_audit_spec.rb +23 -0
- data/spec/controller_spec.rb +37 -0
- data/spec/event_processor_spec.rb +38 -0
- data/spec/factory_spec.rb +28 -0
- data/spec/spec_helper.rb +95 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f7a69b6b0b1590ea99b587a0d5a377b51164ca32
|
4
|
+
data.tar.gz: bcbbea403d691b56aca6b4659eee6c88c6d7081f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c54b20f26179f5a30ac772078f82e959b351542d2c65fec5075cb9c28ded58d51171730417ac8636f42ad75f392190b90c1d3ec0683805daf564248d510eafed
|
7
|
+
data.tar.gz: 0b396cd1900045a94fe5e30d9783bff26bdd6e5a25d1f61221cacbd74130244295e6e0e54d313421b3b37a25e478335826b8547e56efd1a3a0144184b497d64a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.5
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 d.kirichenko
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# ActionAuditor
|
2
|
+
|
3
|
+
Allows to record models changes. It can be ActiveRecord models or any other.
|
4
|
+
Observer for ActiveRecord are included, for other models you should write your own code.
|
5
|
+
You should also take care where to store this changes.
|
6
|
+
|
7
|
+
We split all changes into actions. Action can be rails controller action or resque/sidekiq/rake task.
|
8
|
+
Every action can have unlimited number af attributes. For controller action it can be current user id, response status and anything else.
|
9
|
+
|
10
|
+
There are thee main items in action_auditor structure:
|
11
|
+
|
12
|
+
* ActionObserver
|
13
|
+
* ModelsObserver
|
14
|
+
* Store
|
15
|
+
|
16
|
+
We offer some default implementation for each of them, but your are free to write your own.
|
17
|
+
|
18
|
+
ActionsObserver is a class or module, often mixin. It starts ActionAuditor at the beginning of action and stop at the end.
|
19
|
+
No changes will be stored if ActionAuditor isn't started.
|
20
|
+
It also stores action attributes related to the action. Action attributes can be stored from any place of code
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
ActionAudit.add_params(user_id: user.id)
|
24
|
+
```
|
25
|
+
|
26
|
+
You can use ActionAuditor::Controller for Rails controllers and RescueConcern for resque tasks or write your own.
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require 'action_auditor/controller_concern'
|
30
|
+
class ApplicationController < ActionController::Base
|
31
|
+
include ActionAuditor::ControllerConcern
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
ModelsObserver observe model changes and trigger ActionAuditor to to store them.
|
36
|
+
To observe ActiveRecord changes your should add to config/application.rb
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
config.after_initialize do
|
40
|
+
require 'action_auditor/ar'
|
41
|
+
ActionAuditor::Ar.observe [MyModel1, MyModel2]
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
You can add this code for correct work after code reloading in development into config/environment/development.rb
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
ActionDispatch::Reloader.to_prepare do
|
49
|
+
ActionAuditor::Ar.observe [MyModel1, MyModel2]
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
You could write you own observer for non-ActiveRecord models.
|
54
|
+
|
55
|
+
The last part of the system is Store. We provide default store that save data to log file,
|
56
|
+
but this gem were invented to store data to Postgres database. We don't privide such
|
57
|
+
store becase it depends on how do your want to analize this data. You can set up the store in initializer with
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
ActionAuditor.store = YourStore.new
|
61
|
+
```
|
62
|
+
|
63
|
+
If you want to see some info logs from this gem you should also configure the logger
|
64
|
+
```ruby
|
65
|
+
ActionAuditor.logger = Rails.logger
|
66
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'action_audit/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "action_audit"
|
8
|
+
spec.version = ActionAudit::VERSION
|
9
|
+
spec.authors = ["denis.kirichenko"]
|
10
|
+
spec.email = ["denis.kirichenko@gmail.com"]
|
11
|
+
spec.description = %q{Allows to record models changes}
|
12
|
+
spec.summary = %q{Allows to record models changes. It can be ActiveRecord models or any other. Observer for ActiveRecord are included, for other models you should write your own code. You should also take care where to store this changes.}
|
13
|
+
spec.homepage = "https://github.com/netDalek/action_audit"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'micromachine', '~> 1.1'
|
22
|
+
spec.add_dependency 'activesupport'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
end
|
data/lib/action_audit.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "active_support/core_ext/module/delegation.rb"
|
2
|
+
require 'micromachine'
|
3
|
+
|
4
|
+
require "action_audit/version"
|
5
|
+
require "action_audit/factory"
|
6
|
+
require "action_audit/event_processor"
|
7
|
+
require "action_audit/log_store"
|
8
|
+
|
9
|
+
module ActionAudit
|
10
|
+
class << self
|
11
|
+
delegate :add_change, :add_params, :with_auditor, to: ActionAudit::Factory
|
12
|
+
|
13
|
+
def store
|
14
|
+
@store ||= LogStore.new
|
15
|
+
end
|
16
|
+
attr_writer :store
|
17
|
+
|
18
|
+
attr_accessor :logger
|
19
|
+
|
20
|
+
def info(message)
|
21
|
+
logger.info(message) if logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def error(message)
|
25
|
+
return unless logger
|
26
|
+
if message.respond_to?(:backtrace)
|
27
|
+
bt = Rails.backtrace_cleaner.clean(message.backtrace)
|
28
|
+
logger.error("[action_audit] #{message}: #{bt}")
|
29
|
+
else
|
30
|
+
logger.error("[action_audit] #{message}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActionAudit
|
2
|
+
module Ar
|
3
|
+
class UpdateObserver
|
4
|
+
include Singleton
|
5
|
+
def after_commit(record)
|
6
|
+
changes = record.previous_changes
|
7
|
+
if changes.present?
|
8
|
+
was = Hash[changes.map{|key, value| [key, value.first]}]
|
9
|
+
become = Hash[changes.map{|key, value| [key, value.last]}]
|
10
|
+
ActionAudit.add_change(record, was, become)
|
11
|
+
end
|
12
|
+
rescue Exception => e
|
13
|
+
ActionAudit.error(e)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class DestroyObserver
|
18
|
+
include Singleton
|
19
|
+
def after_commit(record)
|
20
|
+
ActionAudit.add_change(record, record.attributes, {})
|
21
|
+
rescue Exception => e
|
22
|
+
ActionAudit.error(e)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class CreateObserver
|
27
|
+
include Singleton
|
28
|
+
def after_commit(record)
|
29
|
+
ActionAudit.add_change(record, {}, record.attributes)
|
30
|
+
rescue Exception => e
|
31
|
+
ActionAudit.error(e)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.observe(*models)
|
36
|
+
models.flatten.each do |e|
|
37
|
+
cl = e.to_s.camelize.constantize
|
38
|
+
cl.after_commit CreateObserver.instance, on: :create
|
39
|
+
cl.after_commit UpdateObserver.instance, on: :update
|
40
|
+
cl.after_commit DestroyObserver.instance, on: :destroy
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module ActionAudit::ControllerConcern
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
around_filter :audit
|
9
|
+
end
|
10
|
+
|
11
|
+
def audit
|
12
|
+
ActionAudit.info("start audit controller")
|
13
|
+
ActionAudit.with_auditor do
|
14
|
+
ActionAudit.add_params(params.slice("action", "controller"))
|
15
|
+
ActionAudit.add_params(user_id: current_user.id) if current_user
|
16
|
+
begin
|
17
|
+
yield
|
18
|
+
ensure
|
19
|
+
ActionAudit.add_params(status: response.status)
|
20
|
+
ActionAudit.info("add params audit controller #{response.status}")
|
21
|
+
ActionAudit.info("finish audit controller")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class ActionAudit::EventProcessor
|
2
|
+
delegate :info, to: ActionAudit
|
3
|
+
|
4
|
+
def initialize(store)
|
5
|
+
@store = store
|
6
|
+
@params = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_change(entity, was, become)
|
10
|
+
info "adding changeset for entity #{entity}"
|
11
|
+
changes_state.trigger(:entity_changed)
|
12
|
+
@store.save_change(@action_id, entity, was, become)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_params(params)
|
16
|
+
@params.merge!(params)
|
17
|
+
changes_state.trigger(:params_added)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def changes_state
|
23
|
+
@changes_state ||= MicroMachine.new(:nothing).tap do |m|
|
24
|
+
m.when(:entity_changed, :nothing => :changed)
|
25
|
+
m.when(:params_added, :changed => :changed)
|
26
|
+
m.on(:changed) do
|
27
|
+
@action_id = @store.upsert_action(@params, @action_id)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class ActionAudit::Factory
|
2
|
+
class << self
|
3
|
+
def current
|
4
|
+
Thread.current[:action_auditor]
|
5
|
+
end
|
6
|
+
|
7
|
+
def start
|
8
|
+
Thread.current[:action_auditor] = ActionAudit::EventProcessor.new(ActionAudit.store)
|
9
|
+
end
|
10
|
+
|
11
|
+
def flush
|
12
|
+
Thread.current[:action_auditor] = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_auditor(params = {})
|
16
|
+
start
|
17
|
+
add_params(params)
|
18
|
+
yield
|
19
|
+
ensure
|
20
|
+
flush
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_params(*args)
|
24
|
+
current.add_params(*args) if current
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_change(*args)
|
28
|
+
current.add_change(*args) if current
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class LogStore
|
2
|
+
delegate :info, to: ActionAudit
|
3
|
+
|
4
|
+
def upsert_action(params, id)
|
5
|
+
id ||= SecureRandom.uuid
|
6
|
+
info "[action_audit] [#{id}] #{params}"
|
7
|
+
id
|
8
|
+
end
|
9
|
+
|
10
|
+
def save_change(action_id, entity, was, become)
|
11
|
+
params = {
|
12
|
+
entity_id: entity.id,
|
13
|
+
entity_type: entity.class.name,
|
14
|
+
was: was,
|
15
|
+
become: become
|
16
|
+
}
|
17
|
+
info "[audit_changeset] [#{action_id}] #{params}"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActionAudit::ResqueConcern
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def around_perform_auditor(*args)
|
6
|
+
logger_info "audit job with args #{args}"
|
7
|
+
Auditor.start
|
8
|
+
Auditor.add_params(args: args, job_name: self.name)
|
9
|
+
yield
|
10
|
+
ensure
|
11
|
+
Auditor.flush
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def logger_info(str)
|
17
|
+
Rails.logger.info "[Audit] [#{name}] #{str}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActionAudit do
|
4
|
+
let(:params1) { {a: 1} }
|
5
|
+
let(:params2) { {b: 1} }
|
6
|
+
|
7
|
+
let(:entity) { {b: 1} }
|
8
|
+
let(:was) { {c: 1} }
|
9
|
+
let(:become) { {d: 1} }
|
10
|
+
|
11
|
+
let(:store) { spy(:store) }
|
12
|
+
|
13
|
+
it "saves changes when auditor started" do
|
14
|
+
ActionAudit.store = store
|
15
|
+
expect(store).to receive(:upsert_action).with(params1, nil).and_return(1)
|
16
|
+
expect(store).to receive(:save_change).with(1, entity, was, become)
|
17
|
+
|
18
|
+
ActionAudit.with_auditor do
|
19
|
+
ActionAudit.add_params(params1)
|
20
|
+
ActionAudit.add_change(entity, was, become)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'action_audit/controller_concern'
|
4
|
+
require 'active_support/core_ext/hash/slice'
|
5
|
+
|
6
|
+
RSpec.describe ActionAudit::ControllerConcern do
|
7
|
+
class TestController
|
8
|
+
def self.around_filter(_smth)
|
9
|
+
end
|
10
|
+
|
11
|
+
def response
|
12
|
+
OpenStruct.new(status: 200)
|
13
|
+
end
|
14
|
+
|
15
|
+
include ActionAudit::ControllerConcern
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:params) { {"action" => "create", "controller" => "my_controller"} }
|
19
|
+
let(:controller) { TestController.new }
|
20
|
+
let(:response) { OpenStruct.new(status: 200) }
|
21
|
+
|
22
|
+
let(:store) { spy(:store) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
ActionAudit.store = store
|
26
|
+
expect(store).to receive(:upsert_action).with(params, nil).and_return(1).ordered
|
27
|
+
expect(store).to receive(:save_change).with(1, :a, :b, :c)
|
28
|
+
expect(store).to receive(:upsert_action).with(params.merge(status: 200), 1).and_return(1).ordered
|
29
|
+
end
|
30
|
+
|
31
|
+
it "store change while controller action" do
|
32
|
+
expect(controller).to receive_messages(current_user: nil, params: params, response: response)
|
33
|
+
controller.audit do
|
34
|
+
ActionAudit.add_change(:a, :b, :c)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActionAudit::EventProcessor do
|
4
|
+
let(:params1) { {a: 1} }
|
5
|
+
let(:params2) { {b: 1} }
|
6
|
+
|
7
|
+
let(:entity) { {b: 1} }
|
8
|
+
let(:was) { {c: 1} }
|
9
|
+
let(:become) { {d: 1} }
|
10
|
+
|
11
|
+
let(:store) { spy(:store) }
|
12
|
+
|
13
|
+
subject { described_class.new(store) }
|
14
|
+
|
15
|
+
it "doesn't save action without changes" do
|
16
|
+
subject.add_params(params1)
|
17
|
+
subject.add_params(params2)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "saves action with params after first change" do
|
21
|
+
expect(store).to receive(:upsert_action).with(params1.merge(params2), nil).and_return(1)
|
22
|
+
expect(store).to receive(:save_change).with(1, entity, was, become)
|
23
|
+
|
24
|
+
subject.add_params(params1)
|
25
|
+
subject.add_params(params2)
|
26
|
+
subject.add_change(entity, was, become)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "after change added saves action params every time" do
|
30
|
+
expect(store).to receive(:upsert_action).with(params1, nil).ordered.and_return(1)
|
31
|
+
expect(store).to receive(:save_change).with(1, entity, was, become).ordered
|
32
|
+
expect(store).to receive(:upsert_action).with(params1.merge(params2), 1).ordered.and_return(1)
|
33
|
+
|
34
|
+
subject.add_params(params1)
|
35
|
+
subject.add_change(entity, was, become)
|
36
|
+
subject.add_params(params2)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActionAudit::Factory do
|
4
|
+
let(:params1) { {a: 1} }
|
5
|
+
let(:params2) { {b: 1} }
|
6
|
+
|
7
|
+
let(:entity) { {b: 1} }
|
8
|
+
let(:was) { {c: 1} }
|
9
|
+
let(:become) { {d: 1} }
|
10
|
+
|
11
|
+
let(:store) { spy(:store) }
|
12
|
+
|
13
|
+
it "saves changes when auditor started" do
|
14
|
+
ActionAudit.store = store
|
15
|
+
expect(store).to receive(:upsert_action).with(params1, nil).and_return(1)
|
16
|
+
expect(store).to receive(:save_change).with(1, entity, was, become)
|
17
|
+
|
18
|
+
ActionAudit::Factory.with_auditor do
|
19
|
+
described_class.add_params(params1)
|
20
|
+
described_class.add_change(entity, was, become)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "doesn't saves changes when auditor doesn't started" do
|
25
|
+
described_class.add_params(params1)
|
26
|
+
described_class.add_change(entity, was, become)
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'action_audit'
|
2
|
+
require 'rspec'
|
3
|
+
require "rspec/expectations"
|
4
|
+
require 'pry'
|
5
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
6
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
7
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
8
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
9
|
+
#
|
10
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
11
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
12
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
13
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
14
|
+
# a separate helper file that requires the additional dependencies and performs
|
15
|
+
# the additional setup, and require it from the spec files that actually need it.
|
16
|
+
#
|
17
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
18
|
+
# users commonly want.
|
19
|
+
#
|
20
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
21
|
+
RSpec.configure do |config|
|
22
|
+
# rspec-expectations config goes here. You can use an alternate
|
23
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
24
|
+
# assertions if you prefer.
|
25
|
+
config.expect_with :rspec do |expectations|
|
26
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
27
|
+
# and `failure_message` of custom matchers include text for helper methods
|
28
|
+
# defined using `chain`, e.g.:
|
29
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
30
|
+
# # => "be bigger than 2 and smaller than 4"
|
31
|
+
# ...rather than:
|
32
|
+
# # => "be bigger than 2"
|
33
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
34
|
+
end
|
35
|
+
|
36
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
37
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
38
|
+
config.mock_with :rspec do |mocks|
|
39
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
40
|
+
# a real object. This is generally recommended, and will default to
|
41
|
+
# `true` in RSpec 4.
|
42
|
+
mocks.verify_partial_doubles = true
|
43
|
+
end
|
44
|
+
|
45
|
+
config.order = :random
|
46
|
+
|
47
|
+
# The settings below are suggested to provide a good initial experience
|
48
|
+
# with RSpec, but feel free to customize to your heart's content.
|
49
|
+
=begin
|
50
|
+
# These two settings work together to allow you to limit a spec run
|
51
|
+
# to individual examples or groups you care about by tagging them with
|
52
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
53
|
+
# get run.
|
54
|
+
config.filter_run :focus
|
55
|
+
config.run_all_when_everything_filtered = true
|
56
|
+
|
57
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
58
|
+
# For more details, see:
|
59
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
60
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
61
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
62
|
+
config.disable_monkey_patching!
|
63
|
+
|
64
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
65
|
+
# be too noisy due to issues in dependencies.
|
66
|
+
config.warnings = true
|
67
|
+
|
68
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
69
|
+
# file, and it's useful to allow more verbose output when running an
|
70
|
+
# individual spec file.
|
71
|
+
if config.files_to_run.one?
|
72
|
+
# Use the documentation formatter for detailed output,
|
73
|
+
# unless a formatter has already been configured
|
74
|
+
# (e.g. via a command-line flag).
|
75
|
+
config.default_formatter = 'doc'
|
76
|
+
end
|
77
|
+
|
78
|
+
# Print the 10 slowest examples and example groups at the
|
79
|
+
# end of the spec run, to help surface which specs are running
|
80
|
+
# particularly slow.
|
81
|
+
config.profile_examples = 10
|
82
|
+
|
83
|
+
# Run specs in random order to surface order dependencies. If you find an
|
84
|
+
# order dependency and want to debug it, you can fix the order by providing
|
85
|
+
# the seed, which is printed after each run.
|
86
|
+
# --seed 1234
|
87
|
+
# config.order = :random
|
88
|
+
|
89
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
90
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
91
|
+
# test failures related to randomization by passing the same `--seed` value
|
92
|
+
# as the one that triggered the failure.
|
93
|
+
Kernel.srand config.seed
|
94
|
+
=end
|
95
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: action_audit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- denis.kirichenko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: micromachine
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Allows to record models changes
|
70
|
+
email:
|
71
|
+
- denis.kirichenko@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".ruby-version"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- action_audit.gemspec
|
84
|
+
- lib/action_audit.rb
|
85
|
+
- lib/action_audit/ar.rb
|
86
|
+
- lib/action_audit/controller_concern.rb
|
87
|
+
- lib/action_audit/event_processor.rb
|
88
|
+
- lib/action_audit/factory.rb
|
89
|
+
- lib/action_audit/log_store.rb
|
90
|
+
- lib/action_audit/resque_concern.rb
|
91
|
+
- lib/action_audit/version.rb
|
92
|
+
- spec/action_audit_spec.rb
|
93
|
+
- spec/controller_spec.rb
|
94
|
+
- spec/event_processor_spec.rb
|
95
|
+
- spec/factory_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
homepage: https://github.com/netDalek/action_audit
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.2.2
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: Allows to record models changes. It can be ActiveRecord models or any other.
|
121
|
+
Observer for ActiveRecord are included, for other models you should write your own
|
122
|
+
code. You should also take care where to store this changes.
|
123
|
+
test_files:
|
124
|
+
- spec/action_audit_spec.rb
|
125
|
+
- spec/controller_spec.rb
|
126
|
+
- spec/event_processor_spec.rb
|
127
|
+
- spec/factory_spec.rb
|
128
|
+
- spec/spec_helper.rb
|