operator_recordable 1.1.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a738b794ff45332a5df918bcec227d8c22683cefca6505b4127d53ca664ae78
4
- data.tar.gz: 2d895a62c309fc3b45d5b1dc8c9c31eeadf43e580e0fbea8ccb1b565beb50887
3
+ metadata.gz: 49732162b7408905bf8df338339f939127bc749d307fcf6639d52f173c645372
4
+ data.tar.gz: 1e2358023c22551afb02a430d5bb43c4f1908d867616f30e52754564cfb93b27
5
5
  SHA512:
6
- metadata.gz: df72ca9f3c177e9f237bd8af23bbb9ac03df004dfc46a4db268cae137a91a9a80cbcc04c564406d04cb3ae92e51c050ba92ca94d8ebf6ebb7be38e52b03ea4c3
7
- data.tar.gz: cb82594ea68b88414faf85d8ab556f6e58b44ee971b9886d1d34617c0618c290163761309b5e279fd8f4e589f8a7acca0397ef566215f391ea5697d0de94bf32
6
+ metadata.gz: 4453ea3b593441f2761abacdcf3407a9612adbe3d38758a3c6852c0a34b9147fb90d587aea8f95be986aa749611170d8547e5bbe4ab76ea05824a2cd80b11f93
7
+ data.tar.gz: f8833708e12cae1002924cb2d682936f0b5b43d10f65ee7fc4a92b1b2462ce0c1d01adb5431c57236c7064ddb38bf98a970232df3df181b5f97ec97454afed46
@@ -59,15 +59,6 @@ jobs:
59
59
  activerecord: '5.2'
60
60
  plugin: '_with_request_store'
61
61
  experimental: false
62
- # Rails 7.0.1 will start supporting Ruby 3.1, but Rails 7.0.1 has not been released yet
63
- - ruby: '3.1'
64
- activerecord: '7.0'
65
- plugin: ''
66
- experimental: false
67
- - ruby: '3.1'
68
- activerecord: '7.0'
69
- plugin: '_with_request_store'
70
- experimental: false
71
62
  include:
72
63
  - ruby: '2.7'
73
64
  activerecord: '5.2'
data/.rubocop.yml CHANGED
@@ -2,6 +2,7 @@ AllCops:
2
2
  Exclude:
3
3
  - gemfiles/**/*
4
4
  TargetRubyVersion: 2.5
5
+ NewCops: enable
5
6
 
6
7
  Style/AsciiComments:
7
8
  Enabled: false
@@ -23,6 +24,10 @@ Layout/EndOfLine:
23
24
  Layout/LineLength:
24
25
  Max: 128
25
26
 
27
+ Metrics/AbcSize:
28
+ Exclude:
29
+ - spec/**/*
30
+
26
31
  Metrics/BlockLength:
27
32
  Exclude:
28
33
  - spec/**/*
data/Appraisals CHANGED
@@ -32,12 +32,12 @@ appraise "activerecord_6.1_with_request_store" do
32
32
  end
33
33
 
34
34
  appraise "activerecord_7.0" do
35
- gem "activerecord", "~> 7.0.0"
35
+ gem "activerecord", "~> 7.0.1"
36
36
  gem "sqlite3", "~> 1.4"
37
37
  end
38
38
 
39
39
  appraise "activerecord_7.0_with_request_store" do
40
- gem "activerecord", "~> 7.0.0"
40
+ gem "activerecord", "~> 7.0.1"
41
41
  gem "request_store"
42
42
  gem "sqlite3", "~> 1.4"
43
43
  end
data/CHANGELOG.md CHANGED
@@ -1,20 +1,69 @@
1
1
  ## Unreleased
2
2
 
3
+
4
+ ## 1.3.1 (2022-06-20)
5
+
6
+ ### Bug fixes
7
+
8
+ * Fix recording discarded_by if the target table uses optimistic lock
9
+ + [PR#34](https://github.com/yujideveloper/operator_recordable/pull/34)
10
+
11
+
12
+ ## 1.3.0 (2022-06-01)
13
+
14
+ ### Changes
15
+
16
+ * Support discard gem for soft deletes
17
+ + [PR#31](https://github.com/yujideveloper/operator_recordable/pull/31)
18
+ * Get rid of needless guard clauses for ActiveSupport 5.1 and older
19
+ + [PR#32](https://github.com/yujideveloper/operator_recordable/pull/32)
20
+
21
+ ### Misc
22
+
23
+ * Fix RuboCop offenses
24
+ + [PR#33](https://github.com/yujideveloper/operator_recordable/pull/33)
25
+
26
+
27
+ ## 1.2.0 (2022-04-26)
28
+
29
+ ### Changes
30
+
31
+ * Make associations optional
32
+ + [PR#28](https://github.com/yujideveloper/operator_recordable/pull/28)
33
+
34
+ ### Misc
35
+
36
+ * CI against for Rails 7.0 running on Ruby 3.1
37
+ + [PR#26](https://github.com/yujideveloper/operator_recordable/pull/26)
38
+ * Call `super` in `OperatorRecordable::Recorder#initialize`
39
+ + [PR#30](https://github.com/yujideveloper/operator_recordable/pull/30)
40
+
41
+
3
42
  ## 1.1.0 (2022-01-07)
4
43
 
5
44
  ### Changes
6
45
 
7
46
  * Add gem metadata
47
+ + [PR#24](https://github.com/yujideveloper/operator_recordable/pull/24)
8
48
  * Drop Ruby 2.4 support
49
+ + [PR#25](https://github.com/yujideveloper/operator_recordable/pull/25)
9
50
  * Drop ActiveRecord 5.0 and 5.1 support
51
+ + [PR#25](https://github.com/yujideveloper/operator_recordable/pull/25)
10
52
 
11
53
  ### Misc
12
54
 
13
55
  * Introduce Appraisal
56
+ + [PR#19](https://github.com/yujideveloper/operator_recordable/pull/19)
14
57
  * CI against for ActiveRecord 6.1 and 7.0
58
+ + [PR#19](https://github.com/yujideveloper/operator_recordable/pull/19)
59
+ + [PR#22](https://github.com/yujideveloper/operator_recordable/pull/22)
15
60
  * Use GitHub Actions and stop using Travis CI
61
+ + [PR#20](https://github.com/yujideveloper/operator_recordable/pull/20)
16
62
  * CI against for Ruby 3.0 and 3.1
63
+ + [PR#23](https://github.com/yujideveloper/operator_recordable/pull/23)
64
+ + [PR#25](https://github.com/yujideveloper/operator_recordable/pull/25)
17
65
  * Require MFA to release gem
66
+ + [PR#24](https://github.com/yujideveloper/operator_recordable/pull/24)
18
67
 
19
68
 
20
69
  ## 1.0.0 (2020-10-16)
@@ -22,6 +71,7 @@
22
71
  ### Changes
23
72
 
24
73
  * Support Ruby 2.7
74
+ + [PR#14](https://github.com/yujideveloper/operator_recordable/pull/14)
25
75
 
26
76
 
27
77
  ## 0.4.0 (2019-08-22)
@@ -29,10 +79,12 @@
29
79
  ### Changes
30
80
 
31
81
  * Support ActiveRecord 6.0.0
82
+ + [PR#13](https://github.com/yujideveloper/operator_recordable/pull/13)
32
83
 
33
84
  ### Misc
34
85
 
35
86
  * Improve rspec and CI
87
+ + [PR#11](https://github.com/yujideveloper/operator_recordable/pull/11)
36
88
 
37
89
 
38
90
  ## 0.3.0 (2018-10-05)
@@ -40,6 +92,7 @@
40
92
  ### Breaking changes
41
93
 
42
94
  * Change mixin module from `OperatorRecordable` to `OperatorRecordable::Extension`
95
+ + [PR#5](https://github.com/yujideveloper/operator_recordable/pull/5)
43
96
 
44
97
 
45
98
  ## 0.2.0 (2018-09-27)
@@ -47,11 +100,14 @@
47
100
  ### Changes
48
101
 
49
102
  * Add association name options
103
+ + [PR#2](https://github.com/yujideveloper/operator_recordable/pull/2)
50
104
  * Modify not to define unnecessary class methods for ActiveRecord model
105
+ + [PR#3](https://github.com/yujideveloper/operator_recordable/pull/3)
51
106
 
52
107
  ### Misc
53
108
 
54
109
  * Remove unecessary `require`
110
+ + [PR#4](https://github.com/yujideveloper/operator_recordable/pull/4)
55
111
 
56
112
 
57
113
  ## 0.1.1 (2018-09-19)
@@ -59,6 +115,7 @@
59
115
  ### Misc
60
116
 
61
117
  * Refactor internal structures
118
+ + [PR#1](https://github.com/yujideveloper/operator_recordable/pull/1)
62
119
 
63
120
 
64
121
  ## 0.1.0 (2018-09-14)
data/README.md CHANGED
@@ -7,6 +7,8 @@
7
7
  OperatorRecordable is a Rails plugin gem that makes your ActiveRecord models to be saved or logically deleted with automatically set `created_by`, `updated_by`, and `deleted_by`.
8
8
  Also it makes `creator`, `updater`, and `deleter` `belongs_to` association if a class has `created_by`, `updated_by`, or `deleted_by`.
9
9
 
10
+ It also supports `discarded_by` column if [discard gem](https://github.com/jhawthorn/discard) is available.
11
+
10
12
  This gem is inspired by [RecordWithOperator](https://github.com/nay/record_with_operator).
11
13
 
12
14
  ## Installation
@@ -19,7 +21,7 @@ gem 'operator_recordable'
19
21
 
20
22
  And then execute:
21
23
 
22
- $ bundle
24
+ $ bundle install
23
25
 
24
26
  Or install it yourself as:
25
27
 
@@ -38,9 +40,11 @@ OperatorRecordable.config = {
38
40
  creator_column_name: "created_by",
39
41
  updater_column_name: "updated_by",
40
42
  deleter_column_name: "deleted_by",
43
+ discarder_column_name: "discarded_by",
41
44
  creator_association_name: "creator",
42
45
  updater_association_name: "updater",
43
46
  deleter_association_name: "deleter",
47
+ discarder_association_name: "discarder",
44
48
  operator_association_options: {},
45
49
  operator_association_scope: nil,
46
50
  store: :thread_store
@@ -55,10 +59,12 @@ OperatorRecordable.config = {
55
59
  | `creator_column_name` | String | column name of creator. | `"created_by"` |
56
60
  | `updater_column_name` | String | column name of updater. | `"updated_by"` |
57
61
  | `deleter_column_name` | String | column name of deleter. | `"deleted_by"` |
62
+ | `discarder_column_name` | String | column name of discarder. | `"discarded_by"` |
58
63
  | `creator_association_name` | String | association name of creator. | `"creator"` |
59
64
  | `updater_association_name` | String | association name of updater. | `"updater"` |
60
65
  | `deleter_association_name` | String | association name of deleter. | `"deleter"` |
61
- | `operator_association_options` | Hash | options of operator associations. e.g. `{ optional: true }` | `{}` |
66
+ | `discarder_association_name` | String | association name of discarder. | `"discarder"` |
67
+ | `operator_association_options` | Hash | options of operator associations. e.g. `{ touch: true }` | `{}` |
62
68
  | `operator_association_scope` | Proc | The scope of operator associations. e.g. `-> { with_deleted }` | `nil` |
63
69
  | `store` | Enum | operator store. any value of `:thread_store`, `:request_store` or `:current_attributes_store` | `:thread_store` |
64
70
 
@@ -99,7 +105,7 @@ This is default store.
99
105
  This store is implemented by using [RequestStore gem](https://github.com/steveklabnik/request_store).
100
106
  So, this requires RequestStore gem.
101
107
 
102
- RequestStore must be required before OperatorRecordable.
108
+ RequestStore must be loaded before OperatorRecordable.
103
109
 
104
110
  ``` ruby
105
111
  gem "request_store"
@@ -112,15 +118,14 @@ require "request_store"
112
118
  require "operator_recordable"
113
119
  ```
114
120
 
115
- Otherwise, you need to require it yourself.
121
+ Otherwise, you need to load it yourself.
116
122
  ``` ruby
117
123
  require "operator_recordable/store/request_store"
118
124
  ```
119
125
 
120
126
  #### `:current_attributes_store`
121
127
 
122
- This store is implemented by using [`ActiveSupport::CurrentAttributes`](https://api.rubyonrails.org/v5.2.0/classes/ActiveSupport/CurrentAttributes.html).
123
- So, this requires ActiveSupport 5.2 or later.
128
+ This store is implemented by using [`ActiveSupport::CurrentAttributes`](https://api.rubyonrails.org/v5.2.0/classes/ActiveSupport/CurrentAttributes.html).
124
129
 
125
130
 
126
131
  ## Development
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 7.0.0"
5
+ gem "activerecord", "~> 7.0.1"
6
6
  gem "sqlite3", "~> 1.4"
7
7
 
8
8
  gemspec path: "../"
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 7.0.0"
5
+ gem "activerecord", "~> 7.0.1"
6
6
  gem "request_store"
7
7
  gem "sqlite3", "~> 1.4"
8
8
 
@@ -11,8 +11,8 @@ module OperatorRecordable
11
11
  @store = initialize_store
12
12
  end
13
13
 
14
- %i[operator_class_name creator_column_name updater_column_name deleter_column_name
15
- creator_association_name updater_association_name deleter_association_name
14
+ %i[operator_class_name creator_column_name updater_column_name deleter_column_name discarder_column_name
15
+ creator_association_name updater_association_name deleter_association_name discarder_association_name
16
16
  operator_association_options operator_association_scope].each do |name|
17
17
  define_method name do
18
18
  config[name]
@@ -37,9 +37,11 @@ module OperatorRecordable
37
37
  creator_column_name: "created_by",
38
38
  updater_column_name: "updated_by",
39
39
  deleter_column_name: "deleted_by",
40
+ discarder_column_name: "discarded_by",
40
41
  creator_association_name: "creator",
41
42
  updater_association_name: "updater",
42
43
  deleter_association_name: "deleter",
44
+ discarder_association_name: "discarder",
43
45
  operator_association_options: {},
44
46
  operator_association_scope: nil,
45
47
  store: :thread_store
@@ -53,7 +55,7 @@ module OperatorRecordable
53
55
  end
54
56
 
55
57
  class Model
56
- VALID_ACTIONS = %i[create update destroy].freeze
58
+ VALID_ACTIONS = %i[create update destroy discard].freeze
57
59
 
58
60
  def initialize(actions)
59
61
  @actions = actions
@@ -72,6 +74,10 @@ module OperatorRecordable
72
74
  actions.include? :destroy
73
75
  end
74
76
 
77
+ def record_discarder?
78
+ actions.include? :discard
79
+ end
80
+
75
81
  private
76
82
 
77
83
  attr_reader :actions
@@ -5,6 +5,7 @@ require "operator_recordable/configuration"
5
5
  module OperatorRecordable
6
6
  class Recorder < ::Module
7
7
  def initialize(config)
8
+ super()
8
9
  define_activate_method(config)
9
10
  end
10
11
 
@@ -30,6 +31,11 @@ module OperatorRecordable
30
31
  m.__send__(:run_deleter_dsl, self, config)
31
32
  m.__send__(:define_deleter_instance_methods, self, config)
32
33
  end
34
+
35
+ if c.record_discarder?
36
+ m.__send__(:run_discarder_dsl, self, config)
37
+ m.__send__(:define_discarder_instance_methods, self, config)
38
+ end
33
39
  end
34
40
  end
35
41
 
@@ -48,46 +54,63 @@ module OperatorRecordable
48
54
  run_add_association_dsl(:deleter, klass, config)
49
55
  end
50
56
 
57
+ def run_discarder_dsl(klass, config)
58
+ klass.before_discard :"assign_#{config.discarder_association_name}"
59
+ run_add_association_dsl(:discarder, klass, config)
60
+ end
61
+
51
62
  def run_add_association_dsl(type, klass, config)
52
63
  klass.belongs_to config.association_name_for(type).to_sym,
53
64
  config.operator_association_scope,
54
65
  **{ foreign_key: config.column_name_for(type),
55
- class_name: config.operator_class_name }.merge(config.operator_association_options)
66
+ class_name: config.operator_class_name,
67
+ optional: true }.merge(config.operator_association_options)
56
68
  end
57
69
 
58
70
  def define_creator_instance_methods(klass, config)
59
71
  klass.class_eval <<~END_OF_DEF, __FILE__, __LINE__ + 1
60
- private def assign_#{config.creator_association_name}
61
- return unless (op = OperatorRecordable.operator)
62
-
63
- self.#{config.creator_column_name} = op.id
64
- end
72
+ private def assign_#{config.creator_association_name} # private def assign_creator
73
+ return unless (op = OperatorRecordable.operator) # return unless (op = OperatorRecordable.operator)
74
+ #
75
+ self.#{config.creator_column_name} = op.id # self.created_by = op.id
76
+ end # end
65
77
  END_OF_DEF
66
78
  end
67
79
 
68
80
  def define_updater_instance_methods(klass, config)
69
81
  klass.class_eval <<~END_OF_DEF, __FILE__, __LINE__ + 1
70
- private def assign_#{config.updater_association_name}
71
- return if !self.new_record? && !self.changed?
72
- return unless (op = OperatorRecordable.operator)
73
-
74
- self.#{config.updater_column_name} = op.id
75
- end
82
+ private def assign_#{config.updater_association_name} # private def assign_updater
83
+ return if !self.new_record? && !self.changed? # return if !self.new_record? && !self.changed?
84
+ return unless (op = OperatorRecordable.operator) # return unless (op = OperatorRecordable.operator)
85
+ #
86
+ self.#{config.updater_column_name} = op.id # self.updated_by = op.id
87
+ end # end
76
88
  END_OF_DEF
77
89
  end
78
90
 
79
91
  def define_deleter_instance_methods(klass, config)
80
92
  klass.class_eval <<~END_OF_DEF, __FILE__, __LINE__ + 1
81
- private def assign_#{config.deleter_association_name}
82
- return if self.frozen?
83
- return unless (op = OperatorRecordable.operator)
84
-
85
- self
86
- .class
87
- .where(self.class.primary_key => id)
88
- .update_all('#{config.deleter_column_name}' => op.id)
89
- self.#{config.deleter_column_name} = op.id
90
- end
93
+ private def assign_#{config.deleter_association_name} # private def assign_deleter
94
+ return if self.frozen? # return if self.frozen?
95
+ return unless (op = OperatorRecordable.operator) # return unless (op = OperatorRecordable.operator)
96
+ #
97
+ self # self
98
+ .class # .class
99
+ .where(self.class.primary_key => id) # .where(self.class.primary_key => id)
100
+ .update_all('#{config.deleter_column_name}' => op.id) # .update_all('deleted_by' => op.id)
101
+ self.#{config.deleter_column_name} = op.id # self.deleted_by = op.id
102
+ end # end
103
+ END_OF_DEF
104
+ end
105
+
106
+ def define_discarder_instance_methods(klass, config)
107
+ klass.class_eval <<~END_OF_DEF, __FILE__, __LINE__ + 1
108
+ private def assign_#{config.discarder_association_name} # private def assign_discarder
109
+ return if self.frozen? # return if self.frozen?
110
+ return unless (op = OperatorRecordable.operator) # return unless (op = OperatorRecordable.operator)
111
+ #
112
+ self.#{config.discarder_column_name} = op.id # self.discarded_by = op.id
113
+ end # end
91
114
  END_OF_DEF
92
115
  end
93
116
  end
@@ -15,4 +15,4 @@ end
15
15
 
16
16
  require "operator_recordable/store/thread_store"
17
17
  require "operator_recordable/store/request_store" if defined? ::RequestStore
18
- require "operator_recordable/store/current_attributes_store" if defined? ::ActiveSupport::CurrentAttributes
18
+ require "operator_recordable/store/current_attributes_store"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OperatorRecordable
4
- VERSION = "1.1.0"
4
+ VERSION = "1.3.1"
5
5
  end
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
34
34
 
35
35
  # Specify which files should be added to the gem when it is released.
36
36
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
37
- spec.files = Dir.chdir(__dir__) do
37
+ spec.files = Dir.chdir(__dir__) do
38
38
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
39
39
  end
40
40
  spec.bindir = "exe"
@@ -46,9 +46,10 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
46
46
  spec.add_dependency "activerecord", ">= 5.2"
47
47
  spec.add_development_dependency "appraisal", ">= 2.3.0"
48
48
  spec.add_development_dependency "bundler", ">= 1.16"
49
+ spec.add_development_dependency "discard", ">= 1.2"
49
50
  spec.add_development_dependency "pry", ">= 0.10.0"
50
51
  spec.add_development_dependency "rake", ">= 10.0"
51
52
  spec.add_development_dependency "rspec", "~> 3.7"
52
- spec.add_development_dependency "rubocop", ">= 0.78.0"
53
+ spec.add_development_dependency "rubocop", ">= 1.13.0"
53
54
  spec.add_development_dependency "sqlite3", ">= 1.3.13"
54
55
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: operator_recordable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Hanamura
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-06 00:00:00.000000000 Z
11
+ date: 2022-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: discard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: pry
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,14 @@ dependencies:
100
114
  requirements:
101
115
  - - ">="
102
116
  - !ruby/object:Gem::Version
103
- version: 0.78.0
117
+ version: 1.13.0
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
- version: 0.78.0
124
+ version: 1.13.0
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: sqlite3
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -171,7 +185,7 @@ metadata:
171
185
  source_code_uri: https://github.com/yujideveloper/operator_recordable
172
186
  changelog_uri: https://github.com/yujideveloper/operator_recordable/tree/master/CHANGELOG.md
173
187
  rubygems_mfa_required: 'true'
174
- post_install_message:
188
+ post_install_message:
175
189
  rdoc_options: []
176
190
  require_paths:
177
191
  - lib
@@ -186,8 +200,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
200
  - !ruby/object:Gem::Version
187
201
  version: '0'
188
202
  requirements: []
189
- rubygems_version: 3.2.21
190
- signing_key:
203
+ rubygems_version: 3.3.7
204
+ signing_key:
191
205
  specification_version: 4
192
206
  summary: OperatorRecordable is a Rails plugin to set created_by, updated_by, and deleted_by
193
207
  to ActiveRecord objects.