activerecord-userstamp 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -5
  3. data/.rspec +2 -2
  4. data/CHANGELOG.md +80 -0
  5. data/Gemfile +3 -3
  6. data/LICENSE +21 -21
  7. data/README.md +188 -220
  8. data/Rakefile +17 -17
  9. data/activerecord-userstamp.gemspec +34 -34
  10. data/lib/active_record/userstamp.rb +30 -14
  11. data/lib/active_record/userstamp/configuration.rb +49 -0
  12. data/lib/active_record/userstamp/controller_additions.rb +38 -41
  13. data/lib/active_record/userstamp/migration_additions.rb +14 -16
  14. data/lib/active_record/userstamp/model_additions.rb +10 -3
  15. data/lib/active_record/userstamp/stampable.rb +121 -174
  16. data/lib/active_record/userstamp/stamper.rb +47 -39
  17. data/lib/active_record/userstamp/utilities.rb +18 -0
  18. data/lib/active_record/userstamp/version.rb +4 -4
  19. data/lib/activerecord/userstamp.rb +1 -1
  20. data/spec/controllers/posts_controller_spec.rb +46 -46
  21. data/spec/controllers/users_controller_spec.rb +41 -41
  22. data/spec/dummy/README.rdoc +28 -28
  23. data/spec/dummy/Rakefile +6 -6
  24. data/spec/dummy/app/assets/javascripts/application.js +13 -13
  25. data/spec/dummy/app/assets/stylesheets/application.css +15 -15
  26. data/spec/dummy/app/controllers/application_controller.rb +13 -13
  27. data/spec/dummy/app/controllers/posts_controller.rb +32 -32
  28. data/spec/dummy/app/controllers/users_controller.rb +18 -18
  29. data/spec/dummy/app/helpers/application_helper.rb +2 -2
  30. data/spec/dummy/app/models/comment.rb +5 -6
  31. data/spec/dummy/app/models/person.rb +3 -4
  32. data/spec/dummy/app/models/post.rb +14 -13
  33. data/spec/dummy/app/models/user.rb +3 -4
  34. data/spec/dummy/app/views/layouts/application.html.erb +14 -14
  35. data/spec/dummy/bin/bundle +3 -3
  36. data/spec/dummy/bin/rails +4 -4
  37. data/spec/dummy/bin/rake +4 -4
  38. data/spec/dummy/bin/setup +29 -29
  39. data/spec/dummy/config.ru +4 -4
  40. data/spec/dummy/config/application.rb +30 -30
  41. data/spec/dummy/config/boot.rb +5 -5
  42. data/spec/dummy/config/database.yml +23 -25
  43. data/spec/dummy/config/environment.rb +5 -5
  44. data/spec/dummy/config/environments/development.rb +41 -41
  45. data/spec/dummy/config/environments/production.rb +79 -79
  46. data/spec/dummy/config/environments/test.rb +37 -37
  47. data/spec/dummy/config/initializers/assets.rb +11 -11
  48. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -7
  49. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -3
  50. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -4
  51. data/spec/dummy/config/initializers/inflections.rb +16 -16
  52. data/spec/dummy/config/initializers/mime_types.rb +4 -4
  53. data/spec/dummy/config/initializers/session_store.rb +3 -3
  54. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -14
  55. data/spec/dummy/config/locales/en.yml +23 -23
  56. data/spec/dummy/config/routes.rb +56 -56
  57. data/spec/dummy/config/secrets.yml +22 -22
  58. data/spec/dummy/db/schema.rb +45 -55
  59. data/spec/dummy/public/404.html +67 -67
  60. data/spec/dummy/public/422.html +67 -67
  61. data/spec/dummy/public/500.html +66 -66
  62. data/spec/lib/configuration_spec.rb +20 -0
  63. data/spec/lib/migration_spec.rb +55 -12
  64. data/spec/lib/stamping_spec.rb +210 -170
  65. data/spec/lib/userstamp_spec.rb +7 -7
  66. data/spec/rails_helper.rb +7 -7
  67. data/spec/spec_helper.rb +97 -97
  68. data/spec/support/database_helpers.rb +20 -22
  69. metadata +6 -5
  70. data/CHANGELOG +0 -26
  71. data/spec/dummy/app/models/foo.rb +0 -3
  72. data/spec/lib/compatibility_stamping_spec.rb +0 -69
data/Rakefile CHANGED
@@ -1,17 +1,17 @@
1
- require 'bundler/setup'
2
- Bundler::GemHelper.install_tasks
3
-
4
- require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new(:spec)
6
-
7
- task :default => :spec
8
-
9
- require 'rdoc/task'
10
- desc 'Generate documentation for the userstamp plugin.'
11
- Rake::RDocTask.new(:rdoc) do |rdoc|
12
- rdoc.rdoc_dir = 'rdoc'
13
- rdoc.title = 'Userstamp'
14
- rdoc.options << '--line-numbers' << '--inline-source'
15
- rdoc.rdoc_files.include('Readme.rdoc', 'CHANGELOG', 'LICENSE')
16
- rdoc.rdoc_files.include('lib/**/*.rb')
17
- end
1
+ require 'bundler/setup'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ require 'rdoc/task'
10
+ desc 'Generate documentation for the userstamp plugin.'
11
+ Rake::RDocTask.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'Userstamp'
14
+ rdoc.options << '--line-numbers' << '--inline-source'
15
+ rdoc.rdoc_files.include('Readme.rdoc', 'CHANGELOG', 'LICENSE')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
@@ -1,34 +1,34 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'active_record/userstamp/version'
5
-
6
- Gem::Specification.new do |s|
7
- s.name = 'activerecord-userstamp'
8
- s.version = ActiveRecord::Userstamp::VERSION
9
- s.authors = ['Joel Low']
10
- s.email = ['joel@joelsplace.sg']
11
-
12
- s.summary = 'Adds magic creator and updater attributes to your ActiveRecord models.'
13
- s.description = 'This gem 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.'
14
- s.homepage = 'https://github.com/lowjoel/activerecord-userstamp'
15
- s.license = 'MIT'
16
-
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ['lib']
21
-
22
- s.add_dependency 'activesupport', '~> 4.2'
23
- s.add_dependency 'activerecord', '~> 4.2'
24
-
25
- s.add_development_dependency 'actionview', '~> 4.2'
26
- s.add_development_dependency 'tzinfo-data'
27
- s.add_development_dependency 'rake'
28
- s.add_development_dependency 'rdoc'
29
- s.add_development_dependency 'rspec-rails', '~> 3.3'
30
- s.add_development_dependency 'simplecov'
31
- s.add_development_dependency 'coveralls'
32
- s.add_development_dependency 'codeclimate-test-reporter'
33
- s.add_development_dependency 'sqlite3'
34
- end
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'active_record/userstamp/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'activerecord-userstamp'
8
+ s.version = ActiveRecord::Userstamp::VERSION
9
+ s.authors = ['Joel Low']
10
+ s.email = ['joel@joelsplace.sg']
11
+
12
+ s.summary = 'Adds magic creator and updater attributes to your ActiveRecord models.'
13
+ s.description = 'This gem 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.'
14
+ s.homepage = 'https://github.com/lowjoel/activerecord-userstamp'
15
+ s.license = 'MIT'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ['lib']
21
+
22
+ s.add_dependency 'activesupport', '~> 4.2'
23
+ s.add_dependency 'activerecord', '~> 4.2'
24
+
25
+ s.add_development_dependency 'actionview', '~> 4.2'
26
+ s.add_development_dependency 'tzinfo-data'
27
+ s.add_development_dependency 'rake'
28
+ s.add_development_dependency 'rdoc'
29
+ s.add_development_dependency 'rspec-rails', '~> 3.3'
30
+ s.add_development_dependency 'simplecov'
31
+ s.add_development_dependency 'coveralls'
32
+ s.add_development_dependency 'codeclimate-test-reporter'
33
+ s.add_development_dependency 'sqlite3'
34
+ end
@@ -1,14 +1,30 @@
1
- module ActiveRecord::Userstamp
2
- extend ActiveSupport::Autoload
3
-
4
- autoload :Stampable
5
- autoload :Stamper
6
-
7
- eager_autoload do
8
- autoload :ControllerAdditions
9
- autoload :MigrationAdditions
10
- autoload :ModelAdditions
11
- end
12
-
13
- eager_load!
14
- end
1
+ module ActiveRecord::Userstamp
2
+ extend ActiveSupport::Autoload
3
+
4
+ autoload :Configuration
5
+ autoload :Stampable
6
+ autoload :Stamper
7
+ autoload :Utilities
8
+
9
+ eager_autoload do
10
+ autoload :ControllerAdditions
11
+ autoload :MigrationAdditions
12
+ autoload :ModelAdditions
13
+ end
14
+
15
+ # Retrieves the configuration for the userstamp gem.
16
+ #
17
+ # @return [ActiveRecord::Userstamp::Configuration]
18
+ def self.config
19
+ Configuration
20
+ end
21
+
22
+ # Configures the gem.
23
+ #
24
+ # @yield [ActiveRecord::Userstamp::Configuration] The configuration for the gem.
25
+ def self.configure
26
+ yield config
27
+ end
28
+
29
+ eager_load!
30
+ end
@@ -0,0 +1,49 @@
1
+ module ActiveRecord::Userstamp::Configuration
2
+ # !@attribute [r] default_stamper
3
+ # Determines the default model used to stamp other models.
4
+ #
5
+ # By default, this is set to +'User'+.
6
+ def self.default_stamper
7
+ ActiveRecord::Base.stamper_class_name
8
+ end
9
+
10
+ # !@attribute [rw] default_stamper
11
+ # @see {.default_stamper}
12
+ def self.default_stamper=(stamper)
13
+ ActiveRecord::Base.stamper_class_name = stamper
14
+ end
15
+ self.default_stamper = 'User'.freeze
16
+
17
+ # @!attribute [r] default_stamper_class
18
+ # Determines the default model used to stamp other models.
19
+ def self.default_stamper_class
20
+ ActiveRecord::Base.stamper_class
21
+ end
22
+
23
+ # !@attribute [rw] creator_attribute
24
+ # Determines the name of the column in the database which stores the name of the creator.
25
+ #
26
+ # Override the attribute by using the stampable class method within a model.
27
+ #
28
+ # By default, this is set to +:creator_id+.
29
+ mattr_accessor :creator_attribute
30
+ self.creator_attribute = :creator_id
31
+
32
+ # !@attribute [rw] updater_attribute
33
+ # Determines the name of the column in the database which stores the name of the updater.
34
+ #
35
+ # Override the attribute by using the stampable class method within a model.
36
+ #
37
+ # By default, this is set to +:updater_id+.
38
+ mattr_accessor :updater_attribute
39
+ self.updater_attribute = :updater_id
40
+
41
+ # !@attribute [rw] deleter_attribute
42
+ # Determines the name of the column in the database which stores the name of the deleter.
43
+ #
44
+ # Override the attribute by using the stampable class method within a model.
45
+ #
46
+ # By default, this is set to +:deleter_id+.
47
+ mattr_accessor :deleter_attribute
48
+ self.deleter_attribute = :deleter_id
49
+ end
@@ -1,41 +1,38 @@
1
- # The Userstamp module, when included into a controller, adds a before filter
2
- # (named <tt>set_stamper</tt>) and an after filter (name <tt>reset_stamper</tt>).
3
- # These methods assume a couple of things, but can be re-implemented in your
4
- # controller to better suite your application.
5
- #
6
- # See the documentation for <tt>set_stamper</tt> and <tt>reset_stamper</tt> for
7
- # specific implementation details.
8
- module ActiveRecord::Userstamp::ControllerAdditions
9
- def self.included(base) # :nodoc:
10
- base.send :include, InstanceMethods
11
- base.before_filter :set_stamper
12
- base.after_filter :reset_stamper
13
- end
14
-
15
- module InstanceMethods
16
- private
17
- # The <tt>set_stamper</tt> method as implemented here assumes a couple
18
- # of things. First, that you are using a +User+ model as the stamper
19
- # and second that your controller has a <tt>current_user</tt> method
20
- # that contains the currently logged in stamper. If either of these
21
- # are not the case in your application you will want to manually add
22
- # your own implementation of this method to the private section of
23
- # the controller where you are including the Userstamp module.
24
- def set_stamper
25
- User.stamper = self.current_user
26
- end
27
-
28
- # The <tt>reset_stamper</tt> method as implemented here assumes that a
29
- # +User+ model is being used as the stamper. If this is not the case then
30
- # you will need to manually add your own implementation of this method to
31
- # the private section of the controller where you are including the
32
- # Userstamp module.
33
- def reset_stamper
34
- User.reset_stamper
35
- end
36
- end
37
- end
38
-
39
- if defined?(ActionController)
40
- ActionController::Base.send(:include, ActiveRecord::Userstamp::ControllerAdditions)
41
- end
1
+ # The +ControllerAdditions+ module, when included into a controller, adds an +before_action+
2
+ # callback (named +set_stamper+) and an +after_action+ callback (named +reset_stamper+). These
3
+ # methods assume a couple of things, but can be re-implemented in your controller to better suit
4
+ # your application.
5
+ #
6
+ # See the documentation for `set_stamper` and `reset_stamper` for specific implementation details.
7
+ module ActiveRecord::Userstamp::ControllerAdditions
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ before_filter :set_stamper
12
+ after_filter :reset_stamper
13
+ end
14
+
15
+ private
16
+
17
+ # The +set_stamper+ method as implemented here assumes a couple of things. First, that you are
18
+ # using a +User+ model as the stamper and second that your controller has a +current_user+
19
+ # method that contains the currently logged in stamper. If either of these are not the case in
20
+ # your application you will want to manually add your own implementation of this method to the
21
+ # private section of your +ApplicationController+
22
+ def set_stamper
23
+ ActiveRecord::Userstamp.config.default_stamper_class.stamper = current_user
24
+ end
25
+
26
+ # The +reset_stamper+ method as implemented here assumes that a +User+ model is being used as
27
+ # the stamper. If this is not the case then you will need to manually add your own
28
+ # implementation of this method to the private section of your +ApplicationController+
29
+ def reset_stamper
30
+ ActiveRecord::Userstamp.config.default_stamper_class.reset_stamper
31
+ end
32
+ end
33
+
34
+ if defined?(ActionController)
35
+ ActionController::Base.class_eval do
36
+ include ActiveRecord::Userstamp::ControllerAdditions
37
+ end
38
+ end
@@ -1,16 +1,14 @@
1
- module ActiveRecord::Userstamp::MigrationHelper
2
- def self.included(base) # :nodoc:
3
- base.send(:include, InstanceMethods)
4
- end
5
-
6
- module InstanceMethods
7
- def userstamps(include_deleted_by = false, *args)
8
- column(ActiveRecord::Userstamp.compatibility_mode ? :created_by : :creator_id, :integer, *args)
9
- column(ActiveRecord::Userstamp.compatibility_mode ? :updated_by : :updater_id, :integer, *args)
10
- column(ActiveRecord::Userstamp.compatibility_mode ? :deleted_by : :deleter_id, :integer, *args) if include_deleted_by
11
- end
12
- end
13
- end
14
-
15
- ActiveRecord::ConnectionAdapters::TableDefinition.send(:include,
16
- ActiveRecord::Userstamp::MigrationHelper)
1
+ module ActiveRecord::Userstamp::MigrationHelper
2
+ extend ActiveSupport::Concern
3
+
4
+ def userstamps(*args)
5
+ config = ActiveRecord::Userstamp.config
6
+ column(config.creator_attribute, :integer, *args)
7
+ column(config.updater_attribute, :integer, *args)
8
+ column(config.deleter_attribute, :integer, *args) if config.deleter_attribute.present?
9
+ end
10
+ end
11
+
12
+ ActiveRecord::ConnectionAdapters::TableDefinition.class_eval do
13
+ include ActiveRecord::Userstamp::MigrationHelper
14
+ end
@@ -1,3 +1,10 @@
1
- module ActiveRecord::Userstamp::ModelAdditions; end
2
- ActiveRecord::Base.send(:include, ActiveRecord::Userstamp::Stampable)
3
- ActiveRecord::Base.send(:include, ActiveRecord::Userstamp::Stamper)
1
+ module ActiveRecord::Userstamp::ModelAdditions
2
+ extend ActiveSupport::Concern
3
+
4
+ include ActiveRecord::Userstamp::Stampable
5
+ include ActiveRecord::Userstamp::Stamper
6
+ end
7
+
8
+ ActiveRecord::Base.class_eval do
9
+ include ActiveRecord::Userstamp::ModelAdditions
10
+ end
@@ -1,174 +1,121 @@
1
- module ActiveRecord::Userstamp
2
- # Determines what default columns to use for recording the current stamper.
3
- # By default this is set to false, so the plug-in will use columns named
4
- # <tt>creator_id</tt>, <tt>updater_id</tt>, and <tt>deleter_id</tt>.
5
- #
6
- # To turn compatibility mode on, place the following line in your environment.rb
7
- # file:
8
- #
9
- # Ddb::Userstamp.compatibility_mode = true
10
- #
11
- # This will cause the plug-in to use columns named <tt>created_by</tt>,
12
- # <tt>updated_by</tt>, and <tt>deleted_by</tt>.
13
- mattr_accessor :compatibility_mode
14
- @@compatibility_mode = false
15
-
16
- # Extends the stamping functionality of ActiveRecord by automatically recording the model
17
- # responsible for creating, updating, and deleting the current object. See the Stamper
18
- # and Userstamp modules for further documentation on how the entire process works.
19
- module Stampable
20
- def self.included(base) #:nodoc:
21
- super
22
-
23
- base.extend(ClassMethods)
24
- base.class_eval do
25
- include InstanceMethods
26
-
27
- # Should ActiveRecord record userstamps? Defaults to true.
28
- class_attribute :record_userstamp
29
- self.record_userstamp = true
30
-
31
- # Which class is responsible for stamping? Defaults to :user.
32
- class_attribute :stamper_class_name
33
-
34
- # What column should be used for the creator stamp?
35
- # Defaults to :creator_id when compatibility mode is off
36
- # Defaults to :created_by when compatibility mode is on
37
- class_attribute :creator_attribute
38
-
39
- # What column should be used for the updater stamp?
40
- # Defaults to :updater_id when compatibility mode is off
41
- # Defaults to :updated_by when compatibility mode is on
42
- class_attribute :updater_attribute
43
-
44
- # What column should be used for the deleter stamp?
45
- # Defaults to :deleter_id when compatibility mode is off
46
- # Defaults to :deleted_by when compatibility mode is on
47
- class_attribute :deleter_attribute
48
- end
49
- end
50
-
51
- module ClassMethods
52
- # This method is automatically called on for all classes that inherit from
53
- # ActiveRecord, but if you need to customize how the plug-in functions, this is the
54
- # method to use. Here's an example:
55
- #
56
- # class Post < ActiveRecord::Base
57
- # stampable :stamper_class_name => :person,
58
- # :creator_attribute => :create_user,
59
- # :updater_attribute => :update_user,
60
- # :deleter_attribute => :delete_user,
61
- # :deleter => true,
62
- # :with_deleted => true
63
- # end
64
- #
65
- # The method will automatically setup all the associations,
66
- # and create <tt>before_validation</tt> & <tt>before_destroy</tt> callbacks for doing the stamping.
67
- #
68
- # By default, the deleter association and before filter are not defined unless
69
- # you set the :deleter_attribute or set the :deleter option to true.
70
- #
71
- # When using the new acts_as_paranoid gem (https://github.com/goncalossilva/rails3_acts_as_paranoid)
72
- # the :with_deleted option can be used to setup the associations to return objects that have been soft deleted.
73
- #
74
- def stampable(options = {})
75
- compatability = ActiveRecord::Userstamp.compatibility_mode
76
- defaults = {
77
- :stamper_class_name => :user,
78
- :creator_attribute => (compatability ? :created_by : :creator_id),
79
- :updater_attribute => (compatability ? :updated_by : :updater_id),
80
- :deleter_attribute => (compatability ? :deleted_by : :deleter_id),
81
- :deleter => options.has_key?(:deleter_attribute),
82
- :with_deleted => false
83
- }.merge(options)
84
-
85
- self.stamper_class_name = defaults[:stamper_class_name].to_sym
86
- self.creator_attribute = defaults[:creator_attribute].to_sym
87
- self.updater_attribute = defaults[:updater_attribute].to_sym
88
- self.deleter_attribute = defaults[:deleter_attribute].to_sym
89
-
90
- class_eval do
91
- klass = "::#{stamper_class_name.to_s.singularize.camelize}"
92
-
93
- if defaults[:with_deleted]
94
- belongs_to :creator, :class_name => klass, :foreign_key => creator_attribute, :with_deleted => true
95
- belongs_to :updater, :class_name => klass, :foreign_key => updater_attribute, :with_deleted => true
96
- else
97
- belongs_to :creator, :class_name => klass, :foreign_key => creator_attribute
98
- belongs_to :updater, :class_name => klass, :foreign_key => updater_attribute
99
- end
100
-
101
- before_validation :set_updater_attribute
102
- before_validation :set_creator_attribute, :on => :create
103
- before_save :set_updater_attribute
104
- before_save :set_creator_attribute, :on => :create
105
-
106
- if defaults[:deleter]
107
- if defaults[:with_deleted]
108
- belongs_to :deleter, :class_name => klass, :foreign_key => deleter_attribute, :with_deleted => true
109
- else
110
- belongs_to :deleter, :class_name => klass, :foreign_key => deleter_attribute
111
- end
112
-
113
- before_destroy :set_deleter_attribute
114
-
115
- end
116
- end
117
- end
118
-
119
- # Temporarily allows you to turn stamping off. For example:
120
- #
121
- # Post.without_stamps do
122
- # post = Post.find(params[:id])
123
- # post.update_attributes(params[:post])
124
- # post.save
125
- # end
126
- def without_stamps
127
- original_value = self.record_userstamp
128
- self.record_userstamp = false
129
- yield
130
- ensure
131
- self.record_userstamp = original_value
132
- end
133
-
134
- def stamper_class #:nodoc:
135
- stamper_class_name.to_s.camelize.constantize rescue nil
136
- end
137
- end
138
-
139
- module InstanceMethods #:nodoc:
140
- private
141
- def has_stamper?
142
- !self.class.stamper_class.nil? && !self.class.stamper_class.stamper.nil? rescue false
143
- end
144
-
145
- def set_creator_attribute
146
- return unless self.record_userstamp
147
- if respond_to?(self.creator_attribute.to_sym) && has_stamper?
148
- if self.send(self.creator_attribute.to_sym).blank?
149
- self.send("#{self.creator_attribute}=".to_sym, self.class.stamper_class.stamper)
150
- end
151
- end
152
- end
153
-
154
- def set_updater_attribute
155
- return unless self.record_userstamp
156
- # only set updater if the record is new or has changed
157
- # or contains a serialized attribute (in which case the attribute value is always updated)
158
- return unless self.new_record? || self.changed? || self.class.serialized_attributes.present?
159
- if respond_to?(self.updater_attribute.to_sym) && has_stamper?
160
- self.send("#{self.updater_attribute}=".to_sym, self.class.stamper_class.stamper)
161
- end
162
- end
163
-
164
- def set_deleter_attribute
165
- return unless self.record_userstamp
166
- if respond_to?(self.deleter_attribute.to_sym) && has_stamper?
167
- self.send("#{self.deleter_attribute}=".to_sym, self.class.stamper_class.stamper)
168
- save
169
- end
170
- end
171
- #end private
172
- end
173
- end
174
- end
1
+ # Extends the stamping functionality of ActiveRecord by automatically recording the model
2
+ # responsible for creating, updating, and deleting the current object. See the +Stamper+ and
3
+ # +ControllerAdditions+ modules for further documentation on how the entire process works.
4
+ module ActiveRecord::Userstamp::Stampable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ # Should ActiveRecord record userstamps? Defaults to true.
9
+ class_attribute :record_userstamp
10
+ self.record_userstamp = true
11
+
12
+ class_attribute :stamper_class_name
13
+
14
+ before_validation :set_updater_attribute, if: :record_userstamp
15
+ before_validation :set_creator_attribute, on: :create, if: :record_userstamp
16
+ before_save :set_updater_attribute, if: :record_userstamp
17
+ before_save :set_creator_attribute, on: :create, if: :record_userstamp
18
+ before_destroy :set_deleter_attribute, if: :record_userstamp
19
+ end
20
+
21
+ module ClassMethods
22
+ def inherited(klass)
23
+ super
24
+
25
+ klass.class_eval do
26
+ add_userstamp_associations({})
27
+ end
28
+ end
29
+
30
+ # This method customizes how the gem functions. For example:
31
+ #
32
+ # class Post < ActiveRecord::Base
33
+ # stampable stamper_class_name: Person.name,
34
+ # with_deleted: true
35
+ # end
36
+ #
37
+ # The method will set up all the associations. Extra arguments (like +:with_deleted+) will be
38
+ # propagated to the associations.
39
+ #
40
+ # By default, the deleter association is not defined unless the :deleter_attribute is set in
41
+ # the gem configuration.
42
+ def stampable(options = {})
43
+ self.stamper_class_name = options.delete(:stamper_class_name) if options.key?(:stamper_class_name)
44
+
45
+ add_userstamp_associations(options)
46
+ end
47
+
48
+ # Temporarily allows you to turn stamping off. For example:
49
+ #
50
+ # Post.without_stamps do
51
+ # post = Post.find(params[:id])
52
+ # post.update_attributes(params[:post])
53
+ # post.save
54
+ # end
55
+ def without_stamps
56
+ original_value = self.record_userstamp
57
+ self.record_userstamp = false
58
+ yield
59
+ ensure
60
+ self.record_userstamp = original_value
61
+ end
62
+
63
+ def stamper_class #:nodoc:
64
+ stamper_class_name.to_s.camelize.constantize rescue nil
65
+ end
66
+
67
+ private
68
+
69
+ # Defines the associations for Userstamp.
70
+ def add_userstamp_associations(options)
71
+ config = ActiveRecord::Userstamp.config
72
+ klass = stamper_class.try(:name)
73
+ relation_options = options.reverse_merge(class_name: klass)
74
+
75
+ ActiveRecord::Userstamp::Utilities.remove_association(self, :creator)
76
+ ActiveRecord::Userstamp::Utilities.remove_association(self, :updater)
77
+ ActiveRecord::Userstamp::Utilities.remove_association(self, :deleter)
78
+
79
+ belongs_to :creator, relation_options.reverse_merge(foreign_key: config.creator_attribute)
80
+ belongs_to :updater, relation_options.reverse_merge(foreign_key: config.updater_attribute)
81
+
82
+ if config.deleter_attribute
83
+ remove_method(:deleter) if method_defined?(:deleter)
84
+ belongs_to :deleter, relation_options.reverse_merge(foreign_key: config.deleter_attribute)
85
+ end
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def has_stamper?
92
+ !self.class.stamper_class.nil? && !self.class.stamper_class.stamper.nil?
93
+ end
94
+
95
+ def set_creator_attribute
96
+ creator_attribute = ActiveRecord::Userstamp.config.creator_attribute
97
+ return if !has_stamper? || creator_attribute.nil? || !has_attribute?(creator_attribute)
98
+
99
+ current_attribute_value = send(creator_attribute)
100
+ return if current_attribute_value.present?
101
+
102
+ send("#{creator_attribute}=", self.class.stamper_class.stamper)
103
+ end
104
+
105
+ def set_updater_attribute
106
+ updater_attribute = ActiveRecord::Userstamp.config.updater_attribute
107
+ return if !has_stamper? || updater_attribute.nil? || !has_attribute?(updater_attribute)
108
+
109
+ return if !self.new_record? && !self.changed?
110
+
111
+ send("#{updater_attribute}=", self.class.stamper_class.stamper)
112
+ end
113
+
114
+ def set_deleter_attribute
115
+ deleter_attribute = ActiveRecord::Userstamp.config.deleter_attribute
116
+ return if !has_stamper? || deleter_attribute.nil? || !has_attribute?(deleter_attribute)
117
+
118
+ send("#{deleter_attribute}=", self.class.stamper_class.stamper)
119
+ save
120
+ end
121
+ end