magic_userstamp 0.1.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.
Files changed (65) hide show
  1. data/.gitignore +5 -0
  2. data/CHANGELOG +26 -0
  3. data/LICENSE +20 -0
  4. data/README.original +179 -0
  5. data/README.rdoc +64 -0
  6. data/Rakefile +45 -0
  7. data/VERSION +1 -0
  8. data/init.rb +12 -0
  9. data/lib/userstamp/config.rb +119 -0
  10. data/lib/userstamp/controller.rb +43 -0
  11. data/lib/userstamp/event.rb +63 -0
  12. data/lib/userstamp/magic_columns.rb +49 -0
  13. data/lib/userstamp/migration_helper.rb +17 -0
  14. data/lib/userstamp/stampable.rb +147 -0
  15. data/lib/userstamp/stamper.rb +41 -0
  16. data/lib/userstamp.rb +17 -0
  17. data/magic_userstamp.gemspec +124 -0
  18. data/rdoc/classes/Ddb/Controller/Userstamp/InstanceMethods.html +105 -0
  19. data/rdoc/classes/Ddb/Controller/Userstamp.html +125 -0
  20. data/rdoc/classes/Ddb/Controller.html +111 -0
  21. data/rdoc/classes/Ddb/Userstamp/MigrationHelper/InstanceMethods.html +142 -0
  22. data/rdoc/classes/Ddb/Userstamp/MigrationHelper.html +111 -0
  23. data/rdoc/classes/Ddb/Userstamp/Stampable/ClassMethods.html +222 -0
  24. data/rdoc/classes/Ddb/Userstamp/Stampable.html +128 -0
  25. data/rdoc/classes/Ddb/Userstamp/Stamper/ClassMethods.html +142 -0
  26. data/rdoc/classes/Ddb/Userstamp/Stamper/InstanceMethods.html +207 -0
  27. data/rdoc/classes/Ddb/Userstamp/Stamper.html +112 -0
  28. data/rdoc/classes/Ddb/Userstamp.html +121 -0
  29. data/rdoc/created.rid +1 -0
  30. data/rdoc/files/CHANGELOG.html +137 -0
  31. data/rdoc/files/LICENSE.html +129 -0
  32. data/rdoc/files/README.html +341 -0
  33. data/rdoc/files/lib/migration_helper_rb.html +101 -0
  34. data/rdoc/files/lib/stampable_rb.html +101 -0
  35. data/rdoc/files/lib/stamper_rb.html +101 -0
  36. data/rdoc/files/lib/userstamp_rb.html +101 -0
  37. data/rdoc/fr_class_index.html +37 -0
  38. data/rdoc/fr_file_index.html +33 -0
  39. data/rdoc/fr_method_index.html +33 -0
  40. data/rdoc/index.html +24 -0
  41. data/rdoc/rdoc-style.css +208 -0
  42. data/spec/compatibility_stamping_spec.rb +76 -0
  43. data/spec/config_spec.rb +155 -0
  44. data/spec/database.yml +4 -0
  45. data/spec/fixtures/comments.yml +16 -0
  46. data/spec/fixtures/people.yml +11 -0
  47. data/spec/fixtures/posts.yml +9 -0
  48. data/spec/fixtures/users.yml +7 -0
  49. data/spec/magic_column_spec.rb +171 -0
  50. data/spec/posts_controller_spec.rb +41 -0
  51. data/spec/resources/controllers/application_controller.rb +2 -0
  52. data/spec/resources/controllers/posts_controller.rb +26 -0
  53. data/spec/resources/controllers/users_controller.rb +12 -0
  54. data/spec/resources/controllers/userstamp_controller.rb +9 -0
  55. data/spec/resources/models/comment.rb +4 -0
  56. data/spec/resources/models/person.rb +4 -0
  57. data/spec/resources/models/ping.rb +7 -0
  58. data/spec/resources/models/post.rb +4 -0
  59. data/spec/resources/models/user.rb +4 -0
  60. data/spec/schema.rb +56 -0
  61. data/spec/spec.opts +6 -0
  62. data/spec/spec_helper.rb +66 -0
  63. data/spec/stamping_spec.rb +114 -0
  64. data/spec/users_controller_spec.rb +33 -0
  65. metadata +145 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.*~
2
+ *.log
3
+ *.sqlite3
4
+ /coverage
5
+ /pkg
data/CHANGELOG ADDED
@@ -0,0 +1,26 @@
1
+ 2.0 (2-17-2008)
2
+ * [Ben Wyrosdick] - Added a migration helper that gives migration scripts a <tt>userstamps</tt>
3
+ method.
4
+ * [Marshall Roch] - Stamping can be temporarily turned off using the 'without_stamps' class
5
+ method.
6
+ Example:
7
+ Post.without_stamps do
8
+ post = Post.find(params[:id])
9
+ post.update_attributes(params[:post])
10
+ post.save
11
+ end
12
+
13
+ * Models that should receive updates made by 'stampers' now use the acts_as_stampable class
14
+ method. This sets up the belongs_to relationships and also injects private methods for use by
15
+ the individual callback filter methods.
16
+
17
+ * Models that are responsible for updating now use the acts_as_stamper class method. This
18
+ injects the stamper= and stamper methods that are thread safe and should be updated per
19
+ request by a controller.
20
+
21
+ * The Userstamp module is now meant to be included with one of your project's controllers (the
22
+ Application Controller is recommended). It creates a before filter called 'set_stampers' that
23
+ is responsible for setting all the current Stampers.
24
+
25
+ 1.0 (01-18-2006)
26
+ * Initial Release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2008 DeLynn Berry
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.original ADDED
@@ -0,0 +1,179 @@
1
+ = Userstamp Plugin (v 2.0)
2
+
3
+ == Overview
4
+
5
+ The Userstamp Plugin extends ActiveRecord::Base[http://api.rubyonrails.com/classes/ActiveRecord/Base.html] to add automatic updating of 'creator',
6
+ 'updater', and 'deleter' attributes. It is based loosely on the ActiveRecord::Timestamp[http://api.rubyonrails.com/classes/ActiveRecord/Timestamp.html] module.
7
+
8
+ Two class methods (<tt>model_stamper</tt> and <tt>stampable</tt>) are implemented in this plugin.
9
+ The <tt>model_stamper</tt> method is used in models that are responsible for creating, updating, or
10
+ deleting other objects. The <tt>stampable</tt> method is used in models that are subject to being
11
+ created, updated, or deleted by 'stampers'.
12
+
13
+
14
+ == Installation
15
+ Installation of the plugin can be done using the built in Rails plugin script. Issue the following
16
+ command from the root of your application:
17
+
18
+ script/plugin install git://github.com/delynn/userstamp.git
19
+
20
+ Once installed you will need to restart your application for the plugin to be loaded into the Rails
21
+ environment.
22
+
23
+ You might also be interested in using Piston[http://piston.rubyforge.org/index.html] to manage the
24
+ importing and future updating of this plugin.
25
+
26
+ == Usage
27
+ In this new version of the Userstamp plug-in, the assumption is that you have two different
28
+ categories of objects; those that mani˝pulate, and those that are manipulated. For those objects
29
+ that are being manipulated there's the Stampable module and for the manipulators there's the
30
+ Stamper module. There's also the actual Userstamp module for your controllers that assists in
31
+ setting up your environment on a per request basis.
32
+
33
+ To better understand how all this works, I think an example is in order. For this example we will
34
+ assume that a weblog application is comprised of User and Post objects. The first thing we need to
35
+ do is create the migrations for these objects, and the plug-in gives you a <tt>userstamps</tt>
36
+ method for very easily doing this:
37
+
38
+ class CreateUsers < ActiveRecord::Migration
39
+ def self.up
40
+ create_table :users, :force => true do |t|
41
+ t.timestamps
42
+ t.userstamps
43
+ t.name
44
+ end
45
+ end
46
+
47
+ def self.down
48
+ drop_table :users
49
+ end
50
+ end
51
+
52
+ class CreatePosts < ActiveRecord::Migration
53
+ def self.up
54
+ create_table :posts, :force => true do |t|
55
+ t.timestamps
56
+ t.userstamps
57
+ t.title
58
+ end
59
+ end
60
+
61
+ def self.down
62
+ drop_table :posts
63
+ end
64
+ end
65
+
66
+ Second, since Users are going to manipulate other objects in our project, we'll use the
67
+ <tt>model_stamper</tt> method in our User class:
68
+
69
+ class User < ActiveRecord::Base
70
+ model_stamper
71
+ end
72
+
73
+ Finally, we need to setup a controller to set the current user of the application. It's
74
+ recommended that you do this in your ApplicationController:
75
+
76
+ class ApplicationController < ActionController::Base
77
+ include Userstamp
78
+ end
79
+
80
+ If all you are interested in is making sure all tables that have the proper columns are stamped
81
+ by the currently logged in user you can stop right here. More than likely you want all your
82
+ associations setup on your stamped objects, and that's where the <tt>stampable</tt> class method
83
+ comes in. So in our example we'll want to use this method in both our User and Post classes:
84
+
85
+ class User < ActiveRecord::Base
86
+ model_stamper
87
+ stampable
88
+ end
89
+
90
+ class Post < ActiveRecord::Base
91
+ stampable
92
+ end
93
+
94
+ Okay, so what all have we done? The <tt>model_stamper</tt> class method injects two methods into the
95
+ User class. They are #stamper= and #stamper and look like this:
96
+
97
+ def stamper=(object)
98
+ object_stamper = if object.is_a?(ActiveRecord::Base)
99
+ object.send("#{object.class.primary_key}".to_sym)
100
+ else
101
+ object
102
+ end
103
+
104
+ Thread.current["#{self.to_s.downcase}_#{self.object_id}_stamper"] = object_stamper
105
+ end
106
+
107
+ def stamper
108
+ Thread.current["#{self.to_s.downcase}_#{self.object_id}_stamper"]
109
+ end
110
+
111
+ The big change with this new version is that we are now using Thread.current to save the current
112
+ stamper so as to avoid conflict with concurrent requests.
113
+
114
+ The <tt>stampable</tt> method allows you to customize what columns will get stamped, and also
115
+ creates the +creator+, +updater+, and +deleter+ associations.
116
+
117
+ The Userstamp module that we included into our ApplicationController uses the setter method to
118
+ set which user is currently making the request. By default the 'set_stampers' method works perfectly
119
+ with the RestfulAuthentication[http://svn.techno-weenie.net/projects/plugins/restful_authentication] plug-in:
120
+
121
+ def set_stampers
122
+ User.stamper = self.current_user
123
+ end
124
+
125
+ If you aren't using ActsAsAuthenticated, then you need to create your own version of the
126
+ <tt>set_stampers</tt> method in the controller where you've included the Userstamp module.
127
+
128
+ Now, let's get back to the Stampable module (since it really is the interesting one). The Stampable
129
+ module sets up before_* filters that are responsible for setting those attributes at the appropriate
130
+ times. It also creates the belongs_to relationships for you.
131
+
132
+ If you need to customize the columns that are stamped, the <tt>stampable</tt> method can be
133
+ completely customized. Here's an quick example:
134
+
135
+ class Post < ActiveRecord::Base
136
+ acts_as_stampable :stamper_class_name => :person,
137
+ :creator_attribute => :create_user,
138
+ :updater_attribute => :update_user,
139
+ :deleter_attribute => :delete_user
140
+ end
141
+
142
+ If you are upgrading your application from the old version of Userstamp, there is a compatibility
143
+ mode to have the plug-in use the old "_by" columns by default. To enable this mode, add the
144
+ following line to the RAILS_ROOT/config/environment.rb file:
145
+
146
+ Ddb::Userstamp.compatibility_mode = true
147
+
148
+ If you are having a difficult time getting the Userstamp plug-in to work, I recommend you checkout
149
+ the sample application that I created. You can find this application on GitHub[http://github.com/delynn/userstamp_sample]
150
+
151
+ == Uninstall
152
+ Uninstalling the plugin can be done using the built in Rails plugin script. Issue the following
153
+ command from the root of your application:
154
+
155
+ script/plugin remove userstamp
156
+
157
+
158
+ == Documentation
159
+ RDoc has been run on the plugin directory and is available in the doc directory.
160
+
161
+
162
+ == Running Unit Tests
163
+ There are extensive unit tests in the "test" directory of the plugin. These test can be run
164
+ individually by executing the following command from the userstamp directory:
165
+
166
+ ruby test/compatibility_stamping_test.rb
167
+ ruby test/stamping_test.rb
168
+ ruby test/userstamp_controller_test.rb
169
+
170
+
171
+ == Bugs & Feedback
172
+ Bug reports and feedback are welcome via my delynn+userstamp@gmail.com email address. I also
173
+ encouraged everyone to clone the git repository and make modifications--I'll be more than happy
174
+ to merge any changes from other people's branches that would be beneficial to the whole project.
175
+
176
+
177
+ == Credits and Special Thanks
178
+ The original idea for this plugin came from the Rails Wiki article entitled
179
+ {Extending ActiveRecord}[http://wiki.rubyonrails.com/rails/pages/ExtendingActiveRecordExample].
data/README.rdoc ADDED
@@ -0,0 +1,64 @@
1
+ = MagicUserstamp
2
+
3
+ == Install
4
+
5
+ === as a plugin
6
+ ruby script/plugin install git://github.com/akm/magic_userstamp.git
7
+
8
+ === as a gem
9
+ insert following line to config/environment.rb
10
+ config.gem 'magic_userstamp', :version => '0.1.0'
11
+ and
12
+ $ sudo rake gems:install
13
+
14
+ Or install gem manually
15
+
16
+ $ sudo gem install gemcutter
17
+ $ sudo gem tumble
18
+ $ sudo gem install magic_userstamp
19
+
20
+ == Setting
21
+ make config/initializers/magic_userstamp.rb
22
+
23
+ The most simple setting
24
+ Userstamp::Config.setup.defaults
25
+
26
+ Specify User class name
27
+ Userstamp::Config.setup.defaults(:stamper_class_name => 'AdminUser')
28
+
29
+ Actually
30
+ Userstamp::Config.setup.defaults
31
+ means
32
+ Userstamp.config.setup do |config|
33
+ config.with_options(:stamper_class_name => 'User') do |c|
34
+ c.on(:create , :creator_id)
35
+ c.on(:update , :updater_id)
36
+ c.on(:destroy, :deleter_id)
37
+ end
38
+ end
39
+
40
+
41
+ Specify User class name and creator/updater columns
42
+ Userstamp.config.setup do |config|
43
+ config.with_options(:stamper_class_name => 'Person') do |c|
44
+ c.on(:create , :creator_person_id)
45
+ c.on(:update , :updater_person_id)
46
+ c.on(:destroy, :deleter_person_id)
47
+ end
48
+ end
49
+
50
+ Specify target stampable class names
51
+ Userstamp.config.setup do |config|
52
+ config.defaults(:stampable_class_names => %w(Book Schedule))
53
+
54
+ Specify target stampable class names and columns
55
+ Userstamp.config.setup do |config|
56
+ config.with_options(:stampable_class_names => %w(Book Schedule)) do |c|
57
+ c.on(:create , :creator_user_id)
58
+ c.on(:update , :updater_user_id)
59
+ c.on(:destroy, :deleter_user_id)
60
+ end
61
+ end
62
+
63
+ -----
64
+ Copyright (c) 2009 'Takeshi AKIMA, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "magic_userstamp"
8
+ gem.summary = %Q{creator_id/updater_id/deleter_id support with setting outside models}
9
+ gem.description = %Q{This Rails plugin extends ActiveRecord::Base to add automatic updating of created_by and updated_by attributes of your models in much the same way that the ActiveRecord::Timestamp module updates created_(at/on) and updated_(at/on) attributes.}
10
+ gem.email = "akm2000@gmail.com"
11
+ gem.homepage = "http://github.com/akm/magic_userstamp"
12
+ gem.authors = ["akimatter"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "magic_userstamp #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/init.rb ADDED
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'userstamp'
3
+ # コントローラへは自身でincludeしてください。
4
+ # ActionController::Base.send(:include, Userstamp::Controller) if defined?(ActionController)
5
+ ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Userstamp::MigrationHelper)
6
+ if defined?(ActiveRecord)
7
+ ActiveRecord::Base.module_eval do
8
+ include Userstamp::Stampable
9
+ include Userstamp::Stamper
10
+ include Userstamp::MagicColumns # mest be included after Userstamp::Stampable
11
+ end
12
+ end
@@ -0,0 +1,119 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'userstamp'
3
+
4
+ module Userstamp
5
+
6
+ def self.config
7
+ Config.instance
8
+ end
9
+
10
+ class Config
11
+
12
+ class << self
13
+ def instance
14
+ @instance || setup
15
+ end
16
+
17
+ def setup
18
+ @instance = Config.new
19
+ yield(@instance) if block_given?
20
+ @instance
21
+ end
22
+
23
+ def clear
24
+ @instance = nil
25
+ end
26
+ end
27
+
28
+ attr_reader :patterns
29
+ attr_accessor :with_destroy
30
+ attr_accessor :verbose
31
+
32
+ def initialize
33
+ @patterns = []
34
+ @with_destroy = defined?(Caboose::Acts::Paranoid)
35
+ end
36
+
37
+ def pattern_for(klass, column_name)
38
+ patterns.detect{|pattern| pattern.stampable?(klass, column_name)}
39
+ end
40
+
41
+ def on(event_name, column_name, options = nil)
42
+ result = Pattern.new(event_name, column_name, options)
43
+ patterns << result
44
+ result
45
+ end
46
+
47
+ def defaults(options = nil)
48
+ on(:create , :creator_id, options)
49
+ on(:update , :updater_id, options)
50
+ on(:destroy, :deleter_id, options) if with_destroy
51
+ end
52
+
53
+ def compatibles(options = nil)
54
+ on(:create , :created_by, options)
55
+ on(:update , :updated_by, options)
56
+ on(:destroy, :deleted_by, options) if with_destroy
57
+ end
58
+
59
+ def verbose?(klass, column_name)
60
+ case verbose
61
+ when Hash then
62
+ verbose_match?(verbose, klass, column_name)
63
+ when Array then
64
+ verbose.any?{|setting| verbose_match?(setting, klass, column_name)}
65
+ else
66
+ !!verbose
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def verbose_match?(setting, klass, column_name)
73
+ classes = []
74
+ columns = []
75
+ {:classes => classes, :columns => columns}.each do |key, dest|
76
+ if value = setting[key]
77
+ dest.concat(value.is_a?(Array) ? value : [value])
78
+ end
79
+ end
80
+ classes = classes.map{|s| s.to_s}
81
+ columns = columns.map{|s| s.to_s}
82
+ (classes.empty? || classes.include?(klass.name)) &&
83
+ (columns.empty? || columns.include?(column_name.to_s))
84
+ end
85
+
86
+
87
+ class Pattern
88
+ attr_reader :event_name, :column_name, :stampable_class_names
89
+ attr_reader :stamper_class_name, :stamper_attr_name
90
+ attr_reader :options_for_stampable_on
91
+
92
+ def initialize(event_name, column_name, options = nil)
93
+ @event_name = event_name
94
+ @column_name = column_name
95
+ options = {
96
+ :stampable_class_names => nil,
97
+ :stamper_class_name => 'User',
98
+ :stamper_attr_name => nil # sholuld not be only 'id' but PK column name
99
+ }.update(options || {})
100
+ @stampable_class_names = options.delete(:stampable_class_names)
101
+ Userstamp.raise_unless_valid_options_for_stampable_on(options)
102
+ @options_for_stampable_on = options
103
+ @stamper_class_name = options[:stamper_class_name]
104
+ @stamper_attr_name = options[:stamper_attr_name]
105
+ end
106
+
107
+ def stampable?(klass, column_name)
108
+ (stampable_class_names.nil? ? true : stampable_class_names.include?(klass.name)) &&
109
+ (column_name.to_s == self.column_name.to_s)
110
+ end
111
+
112
+ def args_for_stampable_on(column_name = nil)
113
+ [event_name, {:attribute => column_name || self.column_name}.update(@options_for_stampable_on)]
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,43 @@
1
+ require 'userstamp'
2
+
3
+ module Userstamp
4
+ module Controller
5
+ # The Userstamp module, when included into a controller, adds a before filter
6
+ # (named <tt>set_stamper</tt>) and an after filter (name <tt>reset_stamper</tt>).
7
+ # These methods assume a couple of things, but can be re-implemented in your
8
+ # controller to better suite your application.
9
+ #
10
+ # See the documentation for <tt>set_stamper</tt> and <tt>reset_stamper</tt> for
11
+ # specific implementation details.
12
+
13
+ def self.included(base) # :nodoc:
14
+ base.send :include, InstanceMethods
15
+ base.before_filter :set_stamper
16
+ base.after_filter :reset_stamper
17
+ end
18
+
19
+ module InstanceMethods
20
+ private
21
+ # The <tt>set_stamper</tt> method as implemented here assumes a couple
22
+ # of things. First, that you are using a +User+ model as the stamper
23
+ # and second that your controller has a <tt>current_user</tt> method
24
+ # that contains the currently logged in stamper. If either of these
25
+ # are not the case in your application you will want to manually add
26
+ # your own implementation of this method to the private section of
27
+ # the controller where you are including the Userstamp module.
28
+ def set_stamper
29
+ User.stamper = self.current_user
30
+ end
31
+
32
+ # The <tt>reset_stamper</tt> method as implemented here assumes that a
33
+ # +User+ model is being used as the stamper. If this is not the case then
34
+ # you will need to manually add your own implementation of this method to
35
+ # the private section of the controller where you are including the
36
+ # Userstamp module.
37
+ def reset_stamper
38
+ User.reset_stamper
39
+ end
40
+ #end private
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'userstamp'
3
+
4
+ module Userstamp
5
+
6
+ class Event
7
+ attr_reader :name, :actor, :actual_hook, :after_callback
8
+ attr_reader:default_attribute, :default_attribute_compatible
9
+
10
+ def initialize(name, actor, default_attribute_compatible, options = nil)
11
+ @name, @actor = name.to_s, actor.to_s
12
+ @default_attribute = "#{@actor}_id"
13
+ @default_attribute_compatible = default_attribute_compatible
14
+ options = {
15
+ :actual_hook => "before_#{@name.to_s}"
16
+ }.update(options || {})
17
+ @actual_hook = options[:actual_hook]
18
+ @after_callback = options[:after_callback]
19
+ end
20
+
21
+ class << self
22
+ def create(name, actor, default_attribute_compatible, options = nil, &block)
23
+ result = self.new(name, actor, default_attribute_compatible, options, &block)
24
+ @name_hash ||= HashWithIndifferentAccess.new
25
+ @name_hash[name] = result
26
+ @instances ||= []
27
+ @instances << result
28
+ result
29
+ end
30
+
31
+ def [](event_name)
32
+ raise_unless_valid_name(event_name)
33
+ @name_hash[event_name]
34
+ end
35
+
36
+ def each(&block)
37
+ return unless block
38
+ (@instances || []).each(&block)
39
+ end
40
+
41
+ def actor_name(event_name)
42
+ self[event_name].actor
43
+ end
44
+
45
+ def valid_names
46
+ (@instances || []).map(&:name)
47
+ end
48
+
49
+ def valid_name?(event_name)
50
+ valid_names.include?(event_name.to_s)
51
+ end
52
+
53
+ def raise_unless_valid_name(event_name)
54
+ return if valid_name?(event_name)
55
+ raise UserstampError, "Invalid event name '#{event_name.inspect}'. Event name must be one of #{valid_names.inspect}"
56
+ end
57
+ end
58
+ end
59
+
60
+ Event.create(:create , :creator, 'created_by')
61
+ Event.create(:update , :updater, 'updated_by', :actual_hook => :before_save)
62
+ Event.create(:destroy, :deleter, 'deleted_by') #, :after_callback => "save")
63
+ end
@@ -0,0 +1,49 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'userstamp'
3
+
4
+ module Userstamp
5
+
6
+ module MagicColumns
7
+ def self.included(mod)
8
+ mod.extend(ClassMethods)
9
+ mod.instance_eval do
10
+ alias :columns_without_userstamp :columns
11
+ alias :columns :columns_with_userstamp
12
+ alias :stampable_on_without_magic_columns :stampable_on
13
+ alias :stampable_on :stampable_on_with_magic_columns
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ def ignore_userstamp(value = nil)
19
+ @ignore_userstamp = value unless value.nil?
20
+ !!@ignore_userstamp
21
+ end
22
+
23
+ def stampable_on_with_magic_columns(*args, &block)
24
+ ignore_userstamp(true)
25
+ stampable_on_without_magic_columns(*args, &block)
26
+ end
27
+
28
+ def columns_with_userstamp
29
+ result = columns_without_userstamp
30
+ unless @ignore_userstamp || @magic_columns_loaded
31
+ setup_userstamp(result)
32
+ @magic_columns_loaded = true
33
+ end
34
+ result
35
+ end
36
+
37
+ def setup_userstamp(columns)
38
+ config = Userstamp.config
39
+ columns.each do |column|
40
+ next if column.primary
41
+ if pattern = config.pattern_for(self, column.name)
42
+ stampable_on(*pattern.args_for_stampable_on(column.name))
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ require 'userstamp'
2
+
3
+ module Userstamp
4
+ module MigrationHelper
5
+ def self.included(base) # :nodoc:
6
+ base.send(:include, InstanceMethods)
7
+ end
8
+
9
+ module InstanceMethods
10
+ def userstamps(include_deleted_by = false)
11
+ column(Userstamp.compatibility_mode ? :created_by : :creator_id, :integer)
12
+ column(Userstamp.compatibility_mode ? :updated_by : :updater_id, :integer)
13
+ column(Userstamp.compatibility_mode ? :deleted_by : :deleter_id, :integer) if include_deleted_by
14
+ end
15
+ end
16
+ end
17
+ end