activerecord-userstamp 2.1.1 → 3.0.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 (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