espinita 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +60 -0
- data/Rakefile +31 -0
- data/app/models/espinita/audit.rb +41 -0
- data/config/database.yml +24 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20131029200927_create_auditable_audits.rb +15 -0
- data/lib/espinita.rb +16 -0
- data/lib/espinita/auditor.rb +18 -0
- data/lib/espinita/auditor_behavior.rb +83 -0
- data/lib/espinita/auditor_request.rb +13 -0
- data/lib/espinita/engine.rb +18 -0
- data/lib/espinita/version.rb +3 -0
- data/lib/tasks/espinita_tasks.rake +4 -0
- data/spec/controllers/audits_controller_spec.rb +47 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/general_controller.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/assets/stylesheets/general_controller.css +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/general_controller_controller.rb +2 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/general_controller_helper.rb +2 -0
- data/spec/dummy/app/models/general_model.rb +4 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +23 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20131029211126_create_general_models.rb +12 -0
- data/spec/dummy/db/migrate/20131030014901_create_users.rb +11 -0
- data/spec/dummy/db/schema.rb +52 -0
- data/spec/dummy/log/development.log +28 -0
- data/spec/dummy/log/test.log +17268 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/auditable_audits.rb +11 -0
- data/spec/factories/general_models.rb +10 -0
- data/spec/factories/users.rb +9 -0
- data/spec/integration/navigation_test.rb +10 -0
- data/spec/models/espinita/audit_spec.rb +8 -0
- data/spec/models/models/general_model_spec.rb +160 -0
- data/spec/models/models/user_spec.rb +5 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/models.rb +8 -0
- data/spec/support/schema.rb +34 -0
- metadata +291 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 7183b60c3fd3a7d44f78dcb555200525c5dd8030
|
|
4
|
+
data.tar.gz: b9bd2cf0e545a2f111082d14a094691b02aa9bca
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: bfb5056db551350c66078a54de5e644da72d58730cf6ebe06ce7aee533e5fdb76022548737755579c6edbc25c27e1c6a54325d3d9d60c2d82ad30ad021b2391b
|
|
7
|
+
data.tar.gz: 6899fc45eaf3413e0fd068443a20f2e4d2ac185ed535b3ef449a11ed1241fb742a6c36cbe0c1a0e49acdd704a41d4f28ae50acf7e7d491ba123fefccc8349e56
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2013 continuum.cl
|
|
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,60 @@
|
|
|
1
|
+
# Espinita
|
|
2
|
+
|
|
3
|
+
[](http://travis-ci.org/continuum/espinita) [](https://gemnasium.com/continuum/espinita) [](https://coveralls.io/r/continuum/espinita?branch=master)
|
|
4
|
+
=======
|
|
5
|
+
|
|
6
|
+
## Audits activerecord models like a boss
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
Audit activerecord models like a boss, tested in rails 4 and ruby 2.0.0.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
This proyect is heavily based in audited gem.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
In your gemfile
|
|
18
|
+
|
|
19
|
+
gem "espinita"
|
|
20
|
+
|
|
21
|
+
In console
|
|
22
|
+
|
|
23
|
+
$ rake espinita:install:migrations
|
|
24
|
+
$ rake db:migrate
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
class Post < ActiveRecord::Base
|
|
29
|
+
auditable
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
@post.create(title: "an awesome blog post" )
|
|
33
|
+
|
|
34
|
+
Espinita will create an audit by default on creation , edition and destroy:
|
|
35
|
+
|
|
36
|
+
@post.audits.size #=> 1
|
|
37
|
+
|
|
38
|
+
Espinita provides options to include or exclude columns to trigger the creation of audit.
|
|
39
|
+
|
|
40
|
+
class Post < ActiveRecord::Base
|
|
41
|
+
auditable only: [:title] # except: [:some_column]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
And let you declare the callbacks you want for audit creation:
|
|
45
|
+
|
|
46
|
+
class Post < ActiveRecord::Base
|
|
47
|
+
auditable on: [:create] # on: [:create, :update]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
You can find the audits records easily:
|
|
51
|
+
|
|
52
|
+
@post.audits.first #=> #<Espinita::Audit id: 1, auditable_id: 1, auditable_type: "Post", user_id: 1, user_type: "User", audited_changes: {"title"=>[nil, "MyString"], "created_at"=>[nil, 2013-10-30 15:50:14 UTC], "updated_at"=>[nil, 2013-10-30 15:50:14 UTC], "id"=>[nil, 1]}
|
|
53
|
+
|
|
54
|
+
Espinita will save the model changes in a serialized column called audited_changes:
|
|
55
|
+
|
|
56
|
+
@post.audits.firt.audited_changed #=> {"title"=>[nil, "MyString"], "created_at"=>[nil, 2013-10-30 15:50:14 UTC], "updated_at"=>[nil, 2013-10-30 15:50:14 UTC], "id"=>[nil, 1]}
|
|
57
|
+
|
|
58
|
+
Espinita will detect current user when records saved from rails controllers. by default Espinita use current_user method but you can change it
|
|
59
|
+
|
|
60
|
+
Espinita.current_user_method = :authenticated_user
|
data/Rakefile
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#begin
|
|
2
|
+
# require 'bundler/setup'
|
|
3
|
+
#rescue LoadError
|
|
4
|
+
# puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
#end
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require 'rspec/core/rake_task'
|
|
9
|
+
require 'bundler'
|
|
10
|
+
Bundler::GemHelper.install_tasks
|
|
11
|
+
|
|
12
|
+
desc 'Default: run unit specs.'
|
|
13
|
+
task :default => :spec
|
|
14
|
+
|
|
15
|
+
desc 'Test the lazy_high_charts plugin.'
|
|
16
|
+
RSpec::Core::RakeTask.new('spec') do |t|
|
|
17
|
+
t.pattern = FileList['spec/**/*_spec.rb']
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
require 'rdoc/task'
|
|
21
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
23
|
+
rdoc.title = 'Espinita'
|
|
24
|
+
rdoc.options << '--line-numbers'
|
|
25
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
30
|
+
#load 'rails/tasks/engine.rake'
|
|
31
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Espinita
|
|
2
|
+
class Audit < ActiveRecord::Base
|
|
3
|
+
belongs_to :auditable, polymorphic: true
|
|
4
|
+
belongs_to :user, polymorphic: true
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
scope :descending, ->{ reorder("version DESC")}
|
|
8
|
+
scope :creates, ->{ where({:action => 'create'})}
|
|
9
|
+
scope :updates, ->{ where({:action => 'update'})}
|
|
10
|
+
scope :destroys, ->{ where({:action => 'destroy'})}
|
|
11
|
+
|
|
12
|
+
scope :up_until, ->(date_or_time){where("created_at <= ?", date_or_time) }
|
|
13
|
+
scope :from_version, ->(version){where(['version >= ?', version]) }
|
|
14
|
+
scope :to_version, ->(version){where(['version <= ?', version]) }
|
|
15
|
+
scope :auditable_finder, ->(auditable_id, auditable_type){where(auditable_id: auditable_id, auditable_type: auditable_type)}
|
|
16
|
+
|
|
17
|
+
serialize :audited_changes
|
|
18
|
+
|
|
19
|
+
before_create :set_version_number, :set_audit_user
|
|
20
|
+
|
|
21
|
+
# Return all audits older than the current one.
|
|
22
|
+
def ancestors
|
|
23
|
+
self.class.where(['auditable_id = ? and auditable_type = ? and version <= ?',
|
|
24
|
+
auditable_id, auditable_type, version])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
def set_version_number
|
|
29
|
+
max = self.class.auditable_finder(auditable_id, auditable_type).maximum(:version) || 0
|
|
30
|
+
self.version = max + 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def set_audit_user
|
|
34
|
+
self.user = RequestStore.store[:audited_user] if RequestStore.store[:audited_user]
|
|
35
|
+
self.remote_address = RequestStore.store[:audited_ip] if RequestStore.store[:audited_ip]
|
|
36
|
+
|
|
37
|
+
nil # prevent stopping callback chains
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
data/config/database.yml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
sqlite3mem: &SQLITE3MEM
|
|
2
|
+
adapter: sqlite3
|
|
3
|
+
database: ":memory:"
|
|
4
|
+
|
|
5
|
+
sqlite3: &SQLITE
|
|
6
|
+
adapter: sqlite3
|
|
7
|
+
database: audited_test.sqlite3.db
|
|
8
|
+
|
|
9
|
+
postgresql: &POSTGRES
|
|
10
|
+
adapter: postgresql
|
|
11
|
+
username: postgres
|
|
12
|
+
password: postgres
|
|
13
|
+
database: audited_test
|
|
14
|
+
min_messages: ERROR
|
|
15
|
+
|
|
16
|
+
mysql: &MYSQL
|
|
17
|
+
adapter: mysql
|
|
18
|
+
host: localhost
|
|
19
|
+
username: root
|
|
20
|
+
password:
|
|
21
|
+
database: audited_test
|
|
22
|
+
|
|
23
|
+
test:
|
|
24
|
+
<<: *<%= ENV['DB'] || 'SQLITE3MEM' %>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class CreateAuditableAudits < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :espinita_audits do |t|
|
|
4
|
+
t.references :auditable, polymorphic: true, index: true
|
|
5
|
+
t.references :user, polymorphic: true, index: true
|
|
6
|
+
t.text :audited_changes
|
|
7
|
+
t.string :comment
|
|
8
|
+
t.integer :version
|
|
9
|
+
t.string :action
|
|
10
|
+
t.string :remote_address
|
|
11
|
+
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/espinita.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "espinita/engine"
|
|
2
|
+
require "request_store"
|
|
3
|
+
|
|
4
|
+
module Espinita
|
|
5
|
+
|
|
6
|
+
autoload :Auditor, "espinita/auditor"
|
|
7
|
+
autoload :AuditorBehavior, "espinita/auditor_behavior"
|
|
8
|
+
autoload :AuditorRequest, "espinita/auditor_request"
|
|
9
|
+
|
|
10
|
+
attr_accessor :current_user_method
|
|
11
|
+
|
|
12
|
+
def self.current_user_method
|
|
13
|
+
@current_user_method ||= :current_user
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Espinita
|
|
2
|
+
module Auditor
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
include Espinita::AuditorBehavior
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
has_many :audits, :as => :auditable, :class_name => Espinita::Audit.name
|
|
8
|
+
#attr_accessor :audited_user, :audited_ip
|
|
9
|
+
accepts_nested_attributes_for :audits
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module ClassMethods
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Espinita
|
|
2
|
+
module AuditorBehavior
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
class_attribute :excluded_cols
|
|
7
|
+
class_attribute :audit_callbacks
|
|
8
|
+
attr_accessor :audit_comment
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
|
|
13
|
+
@@default_excluded = %w(lock_version created_at updated_at created_on updated_on)
|
|
14
|
+
|
|
15
|
+
def auditable(options = {})
|
|
16
|
+
|
|
17
|
+
self.audit_callbacks = []
|
|
18
|
+
self.audit_callbacks << options[:on] unless options[:on].blank?
|
|
19
|
+
self.audit_callbacks.flatten!
|
|
20
|
+
|
|
21
|
+
after_create :audit_create if self.audit_callbacks.blank? || self.audit_callbacks.include?(:create)
|
|
22
|
+
before_update :audit_update if self.audit_callbacks.blank? || self.audit_callbacks.include?(:update)
|
|
23
|
+
before_destroy :audit_destroy if self.audit_callbacks.blank? || self.audit_callbacks.include?(:destroy)
|
|
24
|
+
|
|
25
|
+
self.excluded_cols = (@@default_excluded)
|
|
26
|
+
|
|
27
|
+
if options[:only]
|
|
28
|
+
options[:only] = [options[:only]].flatten.map { |x| x.to_s }
|
|
29
|
+
self.excluded_cols = (self.column_names - options[:only] )
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if options[:except]
|
|
33
|
+
options[:except] = [options[:except]].flatten.map { |x| x.to_s }
|
|
34
|
+
self.excluded_cols = (@@default_excluded) + options[:except]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def permited_columns
|
|
40
|
+
self.column_names - self.excluded_cols.to_a
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# All audits made during the block called will be recorded as made
|
|
44
|
+
# by +user+. This method is hopefully threadsafe, making it ideal
|
|
45
|
+
# for background operations that require audit information.
|
|
46
|
+
def as_user(user, &block)
|
|
47
|
+
RequestStore.store[:audited_user] = user
|
|
48
|
+
yield
|
|
49
|
+
ensure
|
|
50
|
+
RequestStore.store[:audited_user] = nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# audited attributes detected against permited columns
|
|
56
|
+
def audited_attributes
|
|
57
|
+
self.changes.keys & self.class.permited_columns
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def audit_create
|
|
62
|
+
puts self.class.audit_callbacks
|
|
63
|
+
write_audit(:action => 'create', :audited_changes => changes,
|
|
64
|
+
:comment => audit_comment)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def audit_update
|
|
68
|
+
puts self.class.audit_callbacks
|
|
69
|
+
write_audit(:action => 'update', :audited_changes => changes,
|
|
70
|
+
:comment => audit_comment)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def audit_destroy
|
|
74
|
+
write_audit(:action => 'destroy', :audited_changes => changes,
|
|
75
|
+
:comment => audit_comment)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def write_audit(options)
|
|
79
|
+
self.audits.create(options) unless audited_attributes.blank?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Espinita::AuditorRequest
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
included do
|
|
5
|
+
before_filter :store_audited_user
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def store_audited_user
|
|
9
|
+
RequestStore.store[:audited_user] = self.send(Espinita.current_user_method) #current_user
|
|
10
|
+
|
|
11
|
+
RequestStore.store[:audited_ip] = self.try(:request).try(:remote_ip)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Espinita
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace Espinita
|
|
4
|
+
|
|
5
|
+
config.generators do |g|
|
|
6
|
+
g.test_framework :rspec,
|
|
7
|
+
:fixture_replacement => :factory_girl ,
|
|
8
|
+
:dir => "spec/factories"
|
|
9
|
+
g.integration_tool :rspec
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
initializer "include Auditor request into action controller" do |app|
|
|
13
|
+
ActionController::Base.send(:include, Espinita::AuditorRequest)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class AuditsController < ActionController::Base
|
|
4
|
+
def audit
|
|
5
|
+
@general_model = FactoryGirl.create(:general_model)
|
|
6
|
+
render :nothing => true
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def update_user
|
|
10
|
+
current_user.update_attributes( :password => 'foo')
|
|
11
|
+
render :nothing => true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
attr_accessor :current_user
|
|
17
|
+
attr_accessor :custom_user
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
describe AuditsController do
|
|
22
|
+
|
|
23
|
+
before :each do
|
|
24
|
+
GeneralModel.auditable
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
let( :general_model ){
|
|
28
|
+
FactoryFirl.create(:general_model)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let( :user ) { FactoryGirl.create(:user) }
|
|
32
|
+
|
|
33
|
+
describe "POST audit" do
|
|
34
|
+
|
|
35
|
+
it "should audit user" do
|
|
36
|
+
controller.send(:current_user=, user)
|
|
37
|
+
expect {
|
|
38
|
+
post :audit
|
|
39
|
+
}.to change( Espinita::Audit, :count )
|
|
40
|
+
|
|
41
|
+
assigns(:general_model).audits.last.user.should == user
|
|
42
|
+
assigns(:general_model).audits.last.remote_address.should == "0.0.0.0"
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
== README
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
|
4
|
+
application up and running.
|
|
5
|
+
|
|
6
|
+
Things you may want to cover:
|
|
7
|
+
|
|
8
|
+
* Ruby version
|
|
9
|
+
|
|
10
|
+
* System dependencies
|
|
11
|
+
|
|
12
|
+
* Configuration
|
|
13
|
+
|
|
14
|
+
* Database creation
|
|
15
|
+
|
|
16
|
+
* Database initialization
|
|
17
|
+
|
|
18
|
+
* How to run the test suite
|
|
19
|
+
|
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
|
21
|
+
|
|
22
|
+
* Deployment instructions
|
|
23
|
+
|
|
24
|
+
* ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
|
28
|
+
<tt>rake doc:app</tt>.
|