blamestamp 0.9.0
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.
- data/MIT-LICENSE +20 -0
- data/README.md +137 -0
- data/Rakefile +38 -0
- data/lib/blamestamp/action_controller.rb +24 -0
- data/lib/blamestamp/active_record.rb +84 -0
- data/lib/blamestamp/schema.rb +37 -0
- data/lib/blamestamp/version.rb +3 -0
- data/lib/blamestamp.rb +26 -0
- data/lib/tasks/blamestamp_tasks.rake +4 -0
- data/test/alligators_controller_test.rb +60 -0
- data/test/blameable_test.rb +114 -0
- data/test/blamestamp_test.rb +7 -0
- data/test/devise_works_test.rb +20 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/javascripts/home.js +2 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/home.css +4 -0
- data/test/dummy/app/controllers/alligators_controller.rb +83 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/flags_controller.rb +83 -0
- data/test/dummy/app/controllers/home_controller.rb +4 -0
- data/test/dummy/app/controllers/projects_controller.rb +83 -0
- data/test/dummy/app/helpers/alligators_helper.rb +2 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/flags_helper.rb +2 -0
- data/test/dummy/app/helpers/home_helper.rb +2 -0
- data/test/dummy/app/helpers/projects_helper.rb +2 -0
- data/test/dummy/app/models/alligator.rb +6 -0
- data/test/dummy/app/models/flag.rb +12 -0
- data/test/dummy/app/models/project.rb +6 -0
- data/test/dummy/app/models/user.rb +10 -0
- data/test/dummy/app/views/alligators/_form.html.erb +17 -0
- data/test/dummy/app/views/alligators/edit.html.erb +6 -0
- data/test/dummy/app/views/alligators/index.html.erb +21 -0
- data/test/dummy/app/views/alligators/new.html.erb +5 -0
- data/test/dummy/app/views/alligators/show.html.erb +5 -0
- data/test/dummy/app/views/devise/_links.erb +25 -0
- data/test/dummy/app/views/devise/confirmations/new.html.erb +12 -0
- data/test/dummy/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/test/dummy/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/test/dummy/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
- data/test/dummy/app/views/devise/passwords/edit.html.erb +16 -0
- data/test/dummy/app/views/devise/passwords/new.html.erb +12 -0
- data/test/dummy/app/views/devise/registrations/edit.html.erb +25 -0
- data/test/dummy/app/views/devise/registrations/new.html.erb +18 -0
- data/test/dummy/app/views/devise/sessions/new.html.erb +17 -0
- data/test/dummy/app/views/devise/unlocks/new.html.erb +12 -0
- data/test/dummy/app/views/flags/_form.html.erb +17 -0
- data/test/dummy/app/views/flags/edit.html.erb +6 -0
- data/test/dummy/app/views/flags/index.html.erb +21 -0
- data/test/dummy/app/views/flags/new.html.erb +5 -0
- data/test/dummy/app/views/flags/show.html.erb +5 -0
- data/test/dummy/app/views/home/index.html.erb +8 -0
- data/test/dummy/app/views/layouts/application.html.erb +17 -0
- data/test/dummy/app/views/projects/_form.html.erb +17 -0
- data/test/dummy/app/views/projects/edit.html.erb +6 -0
- data/test/dummy/app/views/projects/index.html.erb +21 -0
- data/test/dummy/app/views/projects/new.html.erb +5 -0
- data/test/dummy/app/views/projects/show.html.erb +5 -0
- data/test/dummy/config/application.rb +57 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +38 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/devise.rb +223 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/devise.en.yml +57 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20120420004117_devise_create_users.rb +49 -0
- data/test/dummy/db/migrate/20120420005606_create_projects.rb +10 -0
- data/test/dummy/db/migrate/20120504022124_create_alligators.rb +11 -0
- data/test/dummy/db/migrate/20120504025050_create_flags.rb +15 -0
- data/test/dummy/db/schema.rb +62 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +780 -0
- data/test/dummy/log/test.log +32640 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/fixtures/alligators.yml +9 -0
- data/test/fixtures/flags.yml +12 -0
- data/test/fixtures/projects.yml +9 -0
- data/test/fixtures/users.yml +6 -0
- data/test/flags_controller_test.rb +72 -0
- data/test/migration_test.rb +24 -0
- data/test/projects_controller_test.rb +65 -0
- data/test/test_helper.rb +23 -0
- metadata +318 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2012 Ryan Cavis
|
|
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,137 @@
|
|
|
1
|
+
Blamestamp
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
Blamestamp is intended as an easy way to record the creating and latest-editing user for an Active Record. It works similarly to the built-in Active Record timestamps module, but in a more configurable and predictable manner. Column names are configurable, as are default values, in case you allow non logged-in users to edit some things. Additionally, it allows configuration of when editing a record will update the blamestamps on a related record.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Requirements
|
|
8
|
+
------------
|
|
9
|
+
|
|
10
|
+
### Ruby and Rails
|
|
11
|
+
|
|
12
|
+
Requires Ruby version **>= 1.9.2** and Rails version **>= 3.0**
|
|
13
|
+
|
|
14
|
+
### Current version limitations
|
|
15
|
+
|
|
16
|
+
Currently only works with a combination of Devise, ActiveRecord and ActiveController.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Installation
|
|
20
|
+
------------
|
|
21
|
+
|
|
22
|
+
Blamestamp should be installed as a gem in your app. Currently, it is only available as the latest-build on github. Fixed versions forth-coming.
|
|
23
|
+
|
|
24
|
+
Include the gem in your Gemfile:
|
|
25
|
+
|
|
26
|
+
gem "blamestamp", :git => "https://github.com/cavis/blamestamp"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Getting Started
|
|
30
|
+
---------------
|
|
31
|
+
|
|
32
|
+
### In your migrations:
|
|
33
|
+
|
|
34
|
+
class CreateFoos < ActiveRecord::Migration
|
|
35
|
+
def change
|
|
36
|
+
create_table :foos do |t|
|
|
37
|
+
t.string :bar
|
|
38
|
+
t.blamestamps
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Or, if modifying an existing model:
|
|
44
|
+
|
|
45
|
+
class AddBlamestampsToFoos < ActiveRecord::Migration
|
|
46
|
+
def up
|
|
47
|
+
change_table :foos do |t|
|
|
48
|
+
t.blamestamps
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
def down
|
|
52
|
+
drop_blamestamps :foos
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### In your model:
|
|
58
|
+
|
|
59
|
+
class Foo < ActiveRecord::Base
|
|
60
|
+
blameable
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Usage
|
|
65
|
+
-----
|
|
66
|
+
|
|
67
|
+
By default, blamestamps adds 4 columns to your models:
|
|
68
|
+
|
|
69
|
+
* `blame_cre_at`
|
|
70
|
+
* `blame_upd_at`
|
|
71
|
+
* `blame_cre_by`
|
|
72
|
+
* `blame_upd_by`
|
|
73
|
+
|
|
74
|
+
When a record is created, `blame_cre_at` and `blame_cre_by` will be set. If no remote-user is logged in (via a controller), `blame_cre_by` will be nil. On initial creation, both `blame_upd_at` and `blame_upd_by` will be nil.
|
|
75
|
+
|
|
76
|
+
When a record is updated for the first time (and every time after), `blame_upd_at` and `blame_upd_by` are modified. Again, `blame_upd_by` will remain nil if there is no remote-user.
|
|
77
|
+
|
|
78
|
+
Additionally, `blameable` adds 2 relations to your models:
|
|
79
|
+
|
|
80
|
+
* `blame_cre_user`
|
|
81
|
+
* `blame_upd_user`
|
|
82
|
+
|
|
83
|
+
These are standard `belongs_to` associations, and will be nil unless the `_at` column is populated.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
Advanced Options
|
|
87
|
+
----------------
|
|
88
|
+
|
|
89
|
+
If that's not enough for you, there are several advanced config options available.
|
|
90
|
+
|
|
91
|
+
### In your migrations:
|
|
92
|
+
|
|
93
|
+
If you don't like the `blame` prefix on the columns, you can change it. In this example it will create columns `blah_cre_at`, `blah_upd_at`, `blah_cre_by`, and `blah_upd_by`.
|
|
94
|
+
|
|
95
|
+
t.blamestamps :prefix => :blah
|
|
96
|
+
|
|
97
|
+
### In your model:
|
|
98
|
+
|
|
99
|
+
If you changed the prefix of the columns in your migration, you should let the model know about that too:
|
|
100
|
+
|
|
101
|
+
blameable :prefix => :blah
|
|
102
|
+
|
|
103
|
+
Or, if you picked something completely off-the-wall in your migration, you can specify each of the 4 columns individually:
|
|
104
|
+
|
|
105
|
+
blameable :cre_at => :made_at, :upd_at => :changed_at, :cre_by => :invented_by, :upd_by => :hacked_by
|
|
106
|
+
|
|
107
|
+
And if you don't like the default association names, you can define those too:
|
|
108
|
+
|
|
109
|
+
blameable :cre_user => :inventor, :upd_user => :hacker
|
|
110
|
+
|
|
111
|
+
Finally, you can cascade modifications from a `blameable` model to one of its associations. Whenever a record of the `blameable` class is inserted, updated, or deleted, the `upd_at`/`upd_by` columns on the associated record will be updated. For example:
|
|
112
|
+
|
|
113
|
+
class Foo < ActiveRecord::Base
|
|
114
|
+
belongs_to :bar
|
|
115
|
+
belongs_to :project
|
|
116
|
+
blameable :cascade => [:project, :bar]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
Or, just specify a single cascade:
|
|
120
|
+
|
|
121
|
+
class Foo < ActiveRecord::Base
|
|
122
|
+
belongs_to :bar
|
|
123
|
+
belongs_to :project
|
|
124
|
+
blameable :cascade => :bar
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
Issues and Contributing
|
|
129
|
+
-----------------------
|
|
130
|
+
|
|
131
|
+
Please, let me know about any bugs/feature-requests via the issues tracker. And if you'd like to contribute, send me a note! Thanks.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
License
|
|
135
|
+
-------
|
|
136
|
+
|
|
137
|
+
Blamestamp is free software, and may be redistributed under the MIT-LICENSE.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
6
|
+
end
|
|
7
|
+
begin
|
|
8
|
+
require 'rdoc/task'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
require 'rdoc/rdoc'
|
|
11
|
+
require 'rake/rdoctask'
|
|
12
|
+
RDoc::Task = Rake::RDocTask
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
17
|
+
rdoc.title = 'Blamestamp'
|
|
18
|
+
rdoc.options << '--line-numbers'
|
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Bundler::GemHelper.install_tasks
|
|
27
|
+
|
|
28
|
+
require 'rake/testtask'
|
|
29
|
+
|
|
30
|
+
Rake::TestTask.new(:test) do |t|
|
|
31
|
+
t.libs << 'lib'
|
|
32
|
+
t.libs << 'test'
|
|
33
|
+
t.pattern = 'test/**/*_test.rb'
|
|
34
|
+
t.verbose = false
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
task :default => :test
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'action_controller'
|
|
2
|
+
|
|
3
|
+
module Blamestamp
|
|
4
|
+
module Blamer
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
self.before_filter :set_blamer
|
|
9
|
+
self.after_filter :unset_blamer
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def set_blamer
|
|
13
|
+
if user_signed_in?
|
|
14
|
+
Blamestamp::set_blame_user(current_user.id)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def unset_blamer
|
|
19
|
+
Blamestamp::unset_blame_user()
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
ActionController::Base.send :include, Blamestamp::Blamer
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
|
|
3
|
+
module Blamestamp
|
|
4
|
+
module Blameable
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def blameable(options = {})
|
|
9
|
+
c = options_to_config(options)
|
|
10
|
+
class_attribute :blameable_config
|
|
11
|
+
self.blameable_config = c
|
|
12
|
+
|
|
13
|
+
# associations
|
|
14
|
+
self.belongs_to c[:cre_user], :class_name => c[:class], :foreign_key => c[:cre_by]
|
|
15
|
+
self.belongs_to c[:upd_user], :class_name => c[:class], :foreign_key => c[:upd_by]
|
|
16
|
+
|
|
17
|
+
# callbacks
|
|
18
|
+
self.before_create :blame_create
|
|
19
|
+
self.before_update :blame_update
|
|
20
|
+
self.after_destroy :blame_destroy
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def options_to_config(opts)
|
|
26
|
+
prefix = opts[:prefix] || "blame"
|
|
27
|
+
cfg = {
|
|
28
|
+
:cre_at => opts[:cre_at] || "#{prefix}_cre_at".to_sym,
|
|
29
|
+
:upd_at => opts[:upd_at] || "#{prefix}_upd_at".to_sym,
|
|
30
|
+
:cre_by => opts[:cre_by] || "#{prefix}_cre_by".to_sym,
|
|
31
|
+
:upd_by => opts[:upd_by] || "#{prefix}_upd_by".to_sym,
|
|
32
|
+
:cre_user => opts[:cre_user] || "#{prefix}_cre_user".to_sym,
|
|
33
|
+
:upd_user => opts[:upd_user] || "#{prefix}_upd_user".to_sym,
|
|
34
|
+
:class => opts[:class] || "User".to_sym,
|
|
35
|
+
:cascade => opts[:cascade] || [],
|
|
36
|
+
}
|
|
37
|
+
cfg[:cascade] = [cfg[:cascade]] if !cfg[:cascade].kind_of?(Array)
|
|
38
|
+
return cfg
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# main blamer workhorse
|
|
43
|
+
def blame_them!(at_key, by_key, force=false)
|
|
44
|
+
at_col = self.blameable_config[at_key]
|
|
45
|
+
by_col = self.blameable_config[by_key]
|
|
46
|
+
|
|
47
|
+
# only blame if it wasn't explicitly set
|
|
48
|
+
if force || !(self.changed - [at_col.to_s, by_col.to_s]).empty?
|
|
49
|
+
self[at_col] = Time.now
|
|
50
|
+
self[by_col] = Blamestamp::get_blame_user
|
|
51
|
+
return true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
return false # nothing saved!
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# cascade the blame up
|
|
58
|
+
def cascade_blame
|
|
59
|
+
self.blameable_config[:cascade].each do |assoc|
|
|
60
|
+
if self.send(assoc)
|
|
61
|
+
self.send(assoc).blame_them!(:upd_at, :upd_by, true)
|
|
62
|
+
self.send(assoc).save :validate => false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# create callback
|
|
68
|
+
def blame_create
|
|
69
|
+
self.cascade_blame() if self.blame_them!(:cre_at, :cre_by)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# update callback
|
|
73
|
+
def blame_update
|
|
74
|
+
self.cascade_blame() if self.blame_them!(:upd_at, :upd_by)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# destory callback
|
|
78
|
+
def blame_destroy
|
|
79
|
+
self.cascade_blame()
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
ActiveRecord::Base.send :include, Blamestamp::Blameable
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Blamestamp
|
|
2
|
+
module Schema
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
def blamestamps(options = {})
|
|
6
|
+
flds = options_to_fields(options)
|
|
7
|
+
column(flds[0], :datetime)
|
|
8
|
+
column(flds[1], :datetime)
|
|
9
|
+
column(flds[2], :integer)
|
|
10
|
+
column(flds[3], :integer)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def drop_blamestamps(tbl_name, options = {})
|
|
14
|
+
flds = options_to_fields(options)
|
|
15
|
+
remove_column tbl_name, :blame_cre_at
|
|
16
|
+
remove_column tbl_name, :blame_upd_at
|
|
17
|
+
remove_column tbl_name, :blame_cre_by
|
|
18
|
+
remove_column tbl_name, :blame_upd_by
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def options_to_fields(opts)
|
|
24
|
+
prefix = opts[:prefix] || 'blame'
|
|
25
|
+
cre_at_fld = opts[:cre_at] || "#{prefix}_cre_at"
|
|
26
|
+
upd_at_fld = opts[:upd_at] || "#{prefix}_upd_at"
|
|
27
|
+
cre_by_fld = opts[:cre_by] || "#{prefix}_cre_by"
|
|
28
|
+
upd_by_fld = opts[:upd_by] || "#{prefix}_upd_by"
|
|
29
|
+
return [cre_at_fld, upd_at_fld, cre_by_fld, upd_by_fld]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# include 3 times, so all variations migrations work
|
|
35
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, Blamestamp::Schema)
|
|
36
|
+
ActiveRecord::ConnectionAdapters::Table.send(:include, Blamestamp::Schema)
|
|
37
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Blamestamp::Schema)
|
data/lib/blamestamp.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Blamestamp
|
|
2
|
+
def self.set_blame_user(id)
|
|
3
|
+
Thread.current[:blamer_id] = id
|
|
4
|
+
end
|
|
5
|
+
def self.get_blame_user
|
|
6
|
+
return Thread.current[:blamer_id]
|
|
7
|
+
end
|
|
8
|
+
def self.unset_blame_user
|
|
9
|
+
Thread.current[:blamer_id] = nil
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# activerecord "blameable"
|
|
14
|
+
if defined?(ActiveRecord)
|
|
15
|
+
require 'blamestamp/active_record'
|
|
16
|
+
require 'blamestamp/schema'
|
|
17
|
+
else
|
|
18
|
+
raise "blamestamp only works with active_record"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# actioncontroller "blamer"
|
|
22
|
+
if defined?(ActionController)
|
|
23
|
+
require 'blamestamp/action_controller'
|
|
24
|
+
else
|
|
25
|
+
raise "blamestamp only works with action_controller"
|
|
26
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class AlligatorsControllerTest < ActionController::TestCase
|
|
4
|
+
test "stamps on create" do
|
|
5
|
+
sign_in :user, users(:harold)
|
|
6
|
+
create_alligator("foo", projects(:secret))
|
|
7
|
+
|
|
8
|
+
assert_not_nil @alligator.gator_cre_at, "created_at not set"
|
|
9
|
+
assert_equal users(:harold).id, @alligator.gator_cre_by, "created_by not set"
|
|
10
|
+
assert_nil @alligator.gator_upd_at, "updated_at was set"
|
|
11
|
+
assert_nil @alligator.gator_upd_by, "updated_by was set"
|
|
12
|
+
|
|
13
|
+
assert_nil @alligator.project.blame_cre_at, "project created_at was set"
|
|
14
|
+
assert_nil @alligator.project.blame_cre_by, "project created_by was set"
|
|
15
|
+
assert_not_nil @alligator.project.blame_upd_at, "project updated_at not set"
|
|
16
|
+
assert_equal users(:harold).id, @alligator.project.blame_upd_by, "project updated_by not set"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test "stamps on update" do
|
|
20
|
+
sign_in :user, users(:isak)
|
|
21
|
+
update_alligator(alligators(:james), "foo")
|
|
22
|
+
|
|
23
|
+
assert_not_nil @alligator.gator_upd_at, "updated_at not set"
|
|
24
|
+
assert_equal users(:isak).id, @alligator.gator_upd_by, "updated_by not set"
|
|
25
|
+
|
|
26
|
+
assert_not_nil @alligator.project.blame_upd_at, "project updated_at not set"
|
|
27
|
+
assert_equal users(:isak).id, @alligator.project.blame_upd_by, "project updated_by not set"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "stamps on destroy" do
|
|
31
|
+
sign_in :user, users(:cameron)
|
|
32
|
+
destroy_alligator(alligators(:james))
|
|
33
|
+
prj = Project.find(projects(:secret).id)
|
|
34
|
+
|
|
35
|
+
assert_not_nil prj.blame_upd_at, "project updated_at not set"
|
|
36
|
+
assert_equal users(:cameron).id, prj.blame_upd_by, "project updated_by not set"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# helper to create and set a new alligator
|
|
42
|
+
def create_alligator(name, project)
|
|
43
|
+
post :create, :alligator => {:name => name, :project_id => project.id}
|
|
44
|
+
assert_response :redirect, "create didn't redirect"
|
|
45
|
+
@alligator = assigns(:alligator)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# helper to update and set an existing alligator
|
|
49
|
+
def update_alligator(gat, name)
|
|
50
|
+
put :update, :id => gat.id, :alligator => {:name => name}
|
|
51
|
+
assert_response :redirect, "update didn't redirect"
|
|
52
|
+
@alligator = assigns(:alligator)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# helper to destroy an alligator
|
|
56
|
+
def destroy_alligator(gat)
|
|
57
|
+
put :destroy, :id => gat.id
|
|
58
|
+
assert_response :redirect, "destroy didn't redirect"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class BlameableTest < ActiveSupport::TestCase
|
|
4
|
+
test "default options" do
|
|
5
|
+
assocs = Project.reflect_on_all_associations.collect {|a| a.name }
|
|
6
|
+
assert assocs.include?(:blame_cre_user), "doesn't include cre_user"
|
|
7
|
+
assert assocs.include?(:blame_upd_user), "doesn't include upd_user"
|
|
8
|
+
|
|
9
|
+
p = projects(:secret)
|
|
10
|
+
set_blamers(p, users(:harold), users(:isak))
|
|
11
|
+
assert_equal users(:harold).email, p.blame_cre_user.email, "incorrect cre_user"
|
|
12
|
+
assert_equal users(:isak).email, p.blame_upd_user.email, "incorrect upd_user"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "prefix option" do
|
|
16
|
+
assocs = Alligator.reflect_on_all_associations.collect {|a| a.name }
|
|
17
|
+
assert assocs.include?(:gator_cre_user), "doesn't include cre_user"
|
|
18
|
+
assert assocs.include?(:gator_upd_user), "doesn't include upd_user"
|
|
19
|
+
|
|
20
|
+
a = alligators(:james)
|
|
21
|
+
set_blamers(a, users(:harold), users(:isak))
|
|
22
|
+
assert_equal users(:harold).email, a.gator_cre_user.email, "incorrect cre_user"
|
|
23
|
+
assert_equal users(:isak).email, a.gator_upd_user.email, "incorrect upd_user"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
test "non array cascade option" do
|
|
27
|
+
a = alligators(:james)
|
|
28
|
+
assert_nil a.project.blame_cre_user, "project already blame-created"
|
|
29
|
+
assert_nil a.project.blame_upd_user, "project already blame-updated"
|
|
30
|
+
|
|
31
|
+
set_blamers(a, users(:isak), users(:isak))
|
|
32
|
+
|
|
33
|
+
assert_nil a.project.blame_cre_user, "project was blame-created"
|
|
34
|
+
assert_not_nil a.project.blame_upd_user, "project not blame-updated"
|
|
35
|
+
assert_equal users(:isak).email, a.project.blame_upd_user.email, "incorrect upd_user"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test "array cascade option" do
|
|
39
|
+
f = flags(:american)
|
|
40
|
+
assert_nil f.project.blame_cre_user, "project already blame-created"
|
|
41
|
+
assert_nil f.project.blame_upd_user, "project already blame-updated"
|
|
42
|
+
assert_nil f.alligator.gator_cre_user, "gator already blame-created"
|
|
43
|
+
assert_nil f.alligator.gator_upd_user, "gator already blame-updated"
|
|
44
|
+
|
|
45
|
+
set_blamers(f, users(:harold), users(:harold))
|
|
46
|
+
|
|
47
|
+
assert_nil f.project.blame_cre_user, "project was blame-created"
|
|
48
|
+
assert_not_nil f.project.blame_upd_user, "project not blame-updated"
|
|
49
|
+
assert_equal users(:harold).email, f.project.blame_upd_user.email, "incorrect upd_user"
|
|
50
|
+
assert_nil f.alligator.gator_cre_user, "gator was blame-created"
|
|
51
|
+
assert_not_nil f.alligator.gator_upd_user, "gator not blame-updated"
|
|
52
|
+
assert_equal users(:harold).email, f.alligator.gator_upd_user.email, "incorrect upd_user"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test "cre_at option" do
|
|
56
|
+
f = Flag.new(:origin => 'aoeu')
|
|
57
|
+
assert_nil f.made_at, "already has cre_at"
|
|
58
|
+
f.save()
|
|
59
|
+
assert_not_nil f.made_at, "didn't set cre_at"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
test "upd_at option" do
|
|
63
|
+
f = flags(:semaphore)
|
|
64
|
+
f.origin = "something else"
|
|
65
|
+
assert_nil f.changed_at, "already has upd_at"
|
|
66
|
+
f.save()
|
|
67
|
+
assert_not_nil f.changed_at, "didn't set upd_at"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
test "cre_by option" do
|
|
71
|
+
f = Flag.new(:origin => 'aoeu')
|
|
72
|
+
assert_nil f.made_by, "already has cre_by"
|
|
73
|
+
f.save()
|
|
74
|
+
assert_not_nil f.made_by, "didn't set cre_by"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
test "upd_by option" do
|
|
78
|
+
f = flags(:semaphore)
|
|
79
|
+
f.origin = "something else"
|
|
80
|
+
assert_nil f.hacked_by, "already has upd_by"
|
|
81
|
+
f.save()
|
|
82
|
+
assert_not_nil f.hacked_by, "didn't set upd_by"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
test "cre_user option" do
|
|
86
|
+
assocs = Flag.reflect_on_all_associations.collect {|f| f.name }
|
|
87
|
+
assert assocs.include?(:maker), "doesn't include cre_user"
|
|
88
|
+
|
|
89
|
+
f = flags(:semaphore)
|
|
90
|
+
set_blamers(f, users(:cameron), users(:cameron))
|
|
91
|
+
assert_equal users(:cameron).email, f.maker.email, "incorrect cre_user"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
test "upd_user option" do
|
|
95
|
+
assocs = Flag.reflect_on_all_associations.collect {|f| f.name }
|
|
96
|
+
assert assocs.include?(:hacker), "doesn't include upd_user"
|
|
97
|
+
|
|
98
|
+
f = flags(:semaphore)
|
|
99
|
+
set_blamers(f, users(:cameron), users(:cameron))
|
|
100
|
+
assert_equal users(:cameron).email, f.hacker.email, "incorrect upd_user"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
def set_blamers(rec, cre_user, upd_user)
|
|
106
|
+
Blamestamp::set_blame_user(cre_user.id)
|
|
107
|
+
rec.blame_them!(:cre_at, :cre_by, true)
|
|
108
|
+
rec.cascade_blame
|
|
109
|
+
Blamestamp::set_blame_user(upd_user.id)
|
|
110
|
+
rec.blame_them!(:upd_at, :upd_by, true)
|
|
111
|
+
rec.cascade_blame
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DeviseWorksTest < ActionController::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@controller = HomeController.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
test "logged out" do
|
|
9
|
+
get :index
|
|
10
|
+
assert_response :success
|
|
11
|
+
assert_select "#loggedout"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test "login" do
|
|
15
|
+
sign_in :user, users(:harold)
|
|
16
|
+
get :index
|
|
17
|
+
assert_response :success
|
|
18
|
+
assert_select "#loggedin"
|
|
19
|
+
end
|
|
20
|
+
end
|