wipe_out 1.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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +50 -0
  3. data/.gitignore +7 -0
  4. data/.markdownlint.json +7 -0
  5. data/.rspec +2 -0
  6. data/.yardopts +6 -0
  7. data/CHANGELOG.md +5 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE +19 -0
  10. data/README.md +58 -0
  11. data/bin/rake +29 -0
  12. data/bin/rspec +29 -0
  13. data/bin/standardrb +29 -0
  14. data/bin/yard +29 -0
  15. data/bin/yardoc +29 -0
  16. data/bin/yri +29 -0
  17. data/docs/development.md +57 -0
  18. data/docs/getting_started.md +350 -0
  19. data/docs/releasing.md +14 -0
  20. data/docs/yard_plugin.rb +12 -0
  21. data/lib/wipe_out.rb +65 -0
  22. data/lib/wipe_out/attribute_strategies/const_value.rb +13 -0
  23. data/lib/wipe_out/attribute_strategies/nullify.rb +5 -0
  24. data/lib/wipe_out/attribute_strategies/randomize.rb +13 -0
  25. data/lib/wipe_out/callback.rb +25 -0
  26. data/lib/wipe_out/callbacks_observer.rb +23 -0
  27. data/lib/wipe_out/config.rb +30 -0
  28. data/lib/wipe_out/execute.rb +31 -0
  29. data/lib/wipe_out/execution/context.rb +34 -0
  30. data/lib/wipe_out/execution/execute_plan.rb +53 -0
  31. data/lib/wipe_out/plans/built_plan.rb +35 -0
  32. data/lib/wipe_out/plans/dsl.rb +117 -0
  33. data/lib/wipe_out/plans/plan.rb +63 -0
  34. data/lib/wipe_out/plans/union.rb +19 -0
  35. data/lib/wipe_out/plugin.rb +31 -0
  36. data/lib/wipe_out/plugins/logger.rb +42 -0
  37. data/lib/wipe_out/validate.rb +48 -0
  38. data/lib/wipe_out/validators/attributes.rb +49 -0
  39. data/lib/wipe_out/validators/base.rb +13 -0
  40. data/lib/wipe_out/validators/defined_relations.rb +26 -0
  41. data/lib/wipe_out/validators/relations_plans.rb +26 -0
  42. data/lib/wipe_out/version.rb +3 -0
  43. data/wipe_out.gemspec +47 -0
  44. metadata +274 -0
@@ -0,0 +1,63 @@
1
+ module WipeOut
2
+ module Plans
3
+ class Plan
4
+ def initialize(config)
5
+ @attributes = {}
6
+ @ignored = []
7
+ @callbacks = []
8
+ @relations = {}
9
+ @on_execute = nil
10
+ @config = config
11
+ end
12
+
13
+ attr_reader :attributes, :ignored, :relations, :callbacks, :config
14
+
15
+ def add_attribute(name, strategy:)
16
+ @attributes[name.to_sym] = strategy
17
+ end
18
+
19
+ def add_relation(name, plan)
20
+ @relations[name.to_sym] = plan
21
+ end
22
+
23
+ def add_relation_union(name, plans, &block)
24
+ @relations[name.to_sym] = Union.new(plans, block)
25
+ end
26
+
27
+ def on_execute(arg = nil, &block)
28
+ @on_execute = arg || block || @on_execute
29
+ end
30
+
31
+ def ignore(name)
32
+ @ignored << name.to_sym
33
+ end
34
+
35
+ def include_plan(other)
36
+ @attributes.merge! other.attributes
37
+ @ignored += other.ignored
38
+ @relations.merge! other.relations
39
+ @on_execute = other.on_execute
40
+ other.callbacks.each do |callback|
41
+ @callbacks << callback
42
+ end
43
+ end
44
+
45
+ # Duck typing for plans union
46
+ def plans
47
+ [self]
48
+ end
49
+
50
+ def establish_execution_plan(_record)
51
+ self
52
+ end
53
+
54
+ def add_callback(callback)
55
+ @callbacks << callback
56
+ end
57
+
58
+ def inspect
59
+ "Plan(attributes=#{attributes.keys})"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ module WipeOut
2
+ module Plans
3
+ class Union
4
+ attr_reader :plans
5
+
6
+ def initialize(plans, selector)
7
+ @plans = plans
8
+ @selector = selector
9
+ end
10
+
11
+ def establish_execution_plan(record)
12
+ plan = @selector.call(record).plan
13
+ raise "Plan #{plan} is not listed in #{@plans}" unless @plans.include?(plan)
14
+
15
+ plan
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module WipeOut
2
+ module Plugin
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def before(*names, &block)
9
+ callback(*names.map { |name| "before_#{name}" }, &block)
10
+ end
11
+
12
+ def after(*names, &block)
13
+ callback(*names.map { |name| "after_#{name}" }, &block)
14
+ end
15
+
16
+ def callback(*names, &block)
17
+ names.each do |name|
18
+ add_callback(Callback.new(name, block))
19
+ end
20
+ end
21
+
22
+ def callbacks
23
+ @callbacks ||= []
24
+ end
25
+
26
+ def add_callback(callback)
27
+ callbacks << callback
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ module WipeOut
2
+ module Plugins
3
+ # Logger plugin module to be used by including it in the plan.
4
+ # When it runs, it prints out debug logs using `WipeOut::Config.logger`
5
+ #
6
+ # @example
7
+ # WipeOut.build_plan do
8
+ # plugin WipeOut::Plugins::Logger
9
+ # wipe_out :name
10
+ # end
11
+ #
12
+ # @example
13
+ # [WipeOut] start plan=Plan(User, attributes=[:name])
14
+ # [WipeOut] executing plan=Plan(User, attributes=[:name]) record_class=User id=#{user.id}
15
+ # [WipeOut] wiped out plan=Plan(User, attributes=[:name]) record_class=User id=#{user.id}
16
+ # [WipeOut] completed plan=Plan(User, attributes=[:name])
17
+ #
18
+ module Logger
19
+ include WipeOut::Plugin
20
+
21
+ before(:plan) do |execution|
22
+ execution.config.logger.debug("[WipeOut] start plan=#{execution.plan.inspect}")
23
+ end
24
+
25
+ after(:plan) do |execution|
26
+ execution.config.logger.debug("[WipeOut] completed plan=#{execution.plan.inspect}")
27
+ end
28
+
29
+ before(:execution) do |execution|
30
+ execution.config.logger.debug(
31
+ "[WipeOut] executing plan=#{execution.plan.inspect} " \
32
+ "record_class=#{execution.record.class} id=#{execution.record.id}"
33
+ )
34
+ end
35
+
36
+ after(:execution) do |execution|
37
+ execution.config.logger.debug("[WipeOut] wiped out plan=#{execution.plan.inspect} " \
38
+ "record_class=#{execution.record.class} id=#{execution.record.id}")
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,48 @@
1
+ module WipeOut
2
+ # Validates plan has proper configuration and that all ActiveRecord class attributes
3
+ # are explicily defined in the plan.
4
+ # Validation is a seperate step, after plan is defined. We don't assume
5
+ # plan is valid stadalone, this allows for plans composition.
6
+ class Validate
7
+ method_object :plan, :ar_class, :config, [:result]
8
+
9
+ VALIDATORS = [
10
+ Validators::Attributes,
11
+ Validators::DefinedRelations,
12
+ Validators::RelationsPlans
13
+ ].freeze
14
+
15
+ # See {Plans::BuiltPlan#validate}
16
+ #
17
+ # @return [Array<String>]
18
+ def call
19
+ VALIDATORS.map do |validator|
20
+ validator.call(plan, ar_class, config, result)
21
+ end
22
+
23
+ result
24
+ end
25
+
26
+ private
27
+
28
+ def result
29
+ @result ||= ValidationResult.new
30
+ end
31
+ end
32
+
33
+ class ValidationResult
34
+ attr_reader :errors
35
+
36
+ def initialize
37
+ @errors = []
38
+ end
39
+
40
+ def valid?
41
+ !errors.any?
42
+ end
43
+
44
+ def add_error(message)
45
+ @errors << message
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,49 @@
1
+ module WipeOut
2
+ module Validators
3
+ class Attributes < Base
4
+ def call
5
+ return if ignored?
6
+
7
+ if missing_attributes.any?
8
+ names = missing_attributes.map { |name| ":#{name}" }.join(", ")
9
+
10
+ result.add_error("#{ar_class.name} plan is missing attributes: #{names}")
11
+ end
12
+
13
+ if non_existing_attributes.any?
14
+ names = non_existing_attributes.map { |name| ":#{name}" }.join(", ")
15
+
16
+ result.add_error("#{ar_class.name} plan has extra attributes: #{names}")
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def missing_attributes
23
+ columns - attributes - ignored_attributes - foreign_keys
24
+ end
25
+
26
+ def non_existing_attributes
27
+ attributes - columns
28
+ end
29
+
30
+ def columns
31
+ ar_class.columns.map(&:name).map(&:to_sym)
32
+ end
33
+
34
+ def attributes
35
+ plan.attributes.keys
36
+ end
37
+
38
+ def ignored_attributes
39
+ plan.ignored + config.ignored_attributes
40
+ end
41
+
42
+ def foreign_keys
43
+ ar_class.reflect_on_all_associations.find_all do |relation|
44
+ relation.is_a?(ActiveRecord::Reflection::BelongsToReflection)
45
+ end.map(&:foreign_key).map(&:to_sym)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,13 @@
1
+ module WipeOut
2
+ module Validators
3
+ class Base
4
+ method_object :plan, :ar_class, :config, :result
5
+
6
+ private
7
+
8
+ def ignored?
9
+ plan.ignored == [WipeOut::IGNORE_ALL]
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module WipeOut
2
+ module Validators
3
+ class DefinedRelations < Base
4
+ def call
5
+ return if ignored?
6
+
7
+ ar_class.reflect_on_all_associations.each do |relation|
8
+ unless indirect_relation?(relation) || ignore_relation?(relation) || plan.relations[relation.name].present?
9
+ result.add_error("#{ar_class.name} relation is missing: :#{relation.name}")
10
+ end
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def indirect_relation?(relation)
17
+ [ActiveRecord::Reflection::ThroughReflection, ActiveRecord::Reflection::BelongsToReflection]
18
+ .include?(relation.class)
19
+ end
20
+
21
+ def ignore_relation?(relation)
22
+ plan.ignored.include?(relation.name) || config.ignored_attributes.include?(relation.name)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module WipeOut
2
+ module Validators
3
+ class RelationsPlans < Base
4
+ def call
5
+ return if ignored?
6
+
7
+ plan.relations.each do |name, plan|
8
+ relation = relation_reflection(name)
9
+ if relation
10
+ plan.plans.each do |potential_plan|
11
+ WipeOut::Validate.call(potential_plan, relation.klass, config, result: result)
12
+ end
13
+ else
14
+ result.add_error("#{ar_class.name} has invalid relation: :#{name}")
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def relation_reflection(name)
22
+ ar_class.reflect_on_association(name)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module WipeOut
2
+ VERSION = "1.0.0".freeze
3
+ end
data/wipe_out.gemspec ADDED
@@ -0,0 +1,47 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ # Maintain your gem's version:
5
+ require "wipe_out/version"
6
+
7
+ # Describe your gem and declare its dependencies:
8
+ Gem::Specification.new do |s|
9
+ s.name = "wipe_out"
10
+ s.version = WipeOut::VERSION
11
+
12
+ s.authors = ["Michał Foryś", "Piotr Król"]
13
+ s.email = %w[developers@globalapptesting.com michal@globalapptesting.com]
14
+
15
+ s.required_ruby_version = ">= 3.0.0"
16
+ s.summary = "Library for removing and clearing data in Rails ActiveRecord models."
17
+ s.description = "Library for removing and clearing data in Rails ActiveRecord models." \
18
+ " Allows to define data removal policy with its own, easy to understand, DSL."
19
+ s.license = "MIT"
20
+ s.homepage = "https://github.com/GlobalAppTesting/wipe_out"
21
+ s.metadata = {
22
+ "homepage_uri" => "https://github.com/GlobalAppTesting/wipe_out",
23
+ "changelog_uri" => "https://github.com/GlobalAppTesting/wipe_out/blob/main/CHANGELOG.md",
24
+ "source_code_uri" => "https://github.com/GlobalAppTesting/wipe_out",
25
+ "bug_tracker_uri" => "https://github.com/GlobalAppTesting/wipe_out/issues"
26
+ }
27
+
28
+ s.files =
29
+ Dir.chdir(File.expand_path(__dir__)) do
30
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
31
+ end
32
+
33
+ s.add_dependency("attr_extras", "~> 6.2")
34
+ s.add_dependency("zeitwerk", "~> 2.4.2")
35
+
36
+ s.add_development_dependency("combustion", "~> 1.3")
37
+ s.add_development_dependency("factory_bot", "~> 6.2")
38
+ s.add_development_dependency("pry", "~> 0.14.1")
39
+ s.add_development_dependency("rails", "~> 6.1")
40
+ s.add_development_dependency("rspec", "~> 3.10")
41
+ s.add_development_dependency("simplecov", "~> 0.21.1")
42
+ s.add_development_dependency("sqlite3", "~> 1.4.2")
43
+ s.add_development_dependency("standard", "~> 1.1.4")
44
+ s.add_development_dependency("super_diff", "~> 0.6.2")
45
+ s.add_development_dependency("webrick")
46
+ s.add_development_dependency("yard", "~> 0.9")
47
+ end
metadata ADDED
@@ -0,0 +1,274 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wipe_out
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Michał Foryś
8
+ - Piotr Król
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2021-08-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: attr_extras
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '6.2'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '6.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: zeitwerk
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 2.4.2
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 2.4.2
42
+ - !ruby/object:Gem::Dependency
43
+ name: combustion
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.3'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.3'
56
+ - !ruby/object:Gem::Dependency
57
+ name: factory_bot
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '6.2'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '6.2'
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 0.14.1
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 0.14.1
84
+ - !ruby/object:Gem::Dependency
85
+ name: rails
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '6.1'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '6.1'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '3.10'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '3.10'
112
+ - !ruby/object:Gem::Dependency
113
+ name: simplecov
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: 0.21.1
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: 0.21.1
126
+ - !ruby/object:Gem::Dependency
127
+ name: sqlite3
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: 1.4.2
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: 1.4.2
140
+ - !ruby/object:Gem::Dependency
141
+ name: standard
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - "~>"
145
+ - !ruby/object:Gem::Version
146
+ version: 1.1.4
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: 1.1.4
154
+ - !ruby/object:Gem::Dependency
155
+ name: super_diff
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: 0.6.2
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: 0.6.2
168
+ - !ruby/object:Gem::Dependency
169
+ name: webrick
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ - !ruby/object:Gem::Dependency
183
+ name: yard
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - "~>"
187
+ - !ruby/object:Gem::Version
188
+ version: '0.9'
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - "~>"
194
+ - !ruby/object:Gem::Version
195
+ version: '0.9'
196
+ description: Library for removing and clearing data in Rails ActiveRecord models.
197
+ Allows to define data removal policy with its own, easy to understand, DSL.
198
+ email:
199
+ - developers@globalapptesting.com
200
+ - michal@globalapptesting.com
201
+ executables: []
202
+ extensions: []
203
+ extra_rdoc_files: []
204
+ files:
205
+ - ".github/workflows/ci.yml"
206
+ - ".gitignore"
207
+ - ".markdownlint.json"
208
+ - ".rspec"
209
+ - ".yardopts"
210
+ - CHANGELOG.md
211
+ - Gemfile
212
+ - LICENSE
213
+ - README.md
214
+ - bin/rake
215
+ - bin/rspec
216
+ - bin/standardrb
217
+ - bin/yard
218
+ - bin/yardoc
219
+ - bin/yri
220
+ - docs/development.md
221
+ - docs/getting_started.md
222
+ - docs/releasing.md
223
+ - docs/yard_plugin.rb
224
+ - lib/wipe_out.rb
225
+ - lib/wipe_out/attribute_strategies/const_value.rb
226
+ - lib/wipe_out/attribute_strategies/nullify.rb
227
+ - lib/wipe_out/attribute_strategies/randomize.rb
228
+ - lib/wipe_out/callback.rb
229
+ - lib/wipe_out/callbacks_observer.rb
230
+ - lib/wipe_out/config.rb
231
+ - lib/wipe_out/execute.rb
232
+ - lib/wipe_out/execution/context.rb
233
+ - lib/wipe_out/execution/execute_plan.rb
234
+ - lib/wipe_out/plans/built_plan.rb
235
+ - lib/wipe_out/plans/dsl.rb
236
+ - lib/wipe_out/plans/plan.rb
237
+ - lib/wipe_out/plans/union.rb
238
+ - lib/wipe_out/plugin.rb
239
+ - lib/wipe_out/plugins/logger.rb
240
+ - lib/wipe_out/validate.rb
241
+ - lib/wipe_out/validators/attributes.rb
242
+ - lib/wipe_out/validators/base.rb
243
+ - lib/wipe_out/validators/defined_relations.rb
244
+ - lib/wipe_out/validators/relations_plans.rb
245
+ - lib/wipe_out/version.rb
246
+ - wipe_out.gemspec
247
+ homepage: https://github.com/GlobalAppTesting/wipe_out
248
+ licenses:
249
+ - MIT
250
+ metadata:
251
+ homepage_uri: https://github.com/GlobalAppTesting/wipe_out
252
+ changelog_uri: https://github.com/GlobalAppTesting/wipe_out/blob/main/CHANGELOG.md
253
+ source_code_uri: https://github.com/GlobalAppTesting/wipe_out
254
+ bug_tracker_uri: https://github.com/GlobalAppTesting/wipe_out/issues
255
+ post_install_message:
256
+ rdoc_options: []
257
+ require_paths:
258
+ - lib
259
+ required_ruby_version: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - ">="
262
+ - !ruby/object:Gem::Version
263
+ version: 3.0.0
264
+ required_rubygems_version: !ruby/object:Gem::Requirement
265
+ requirements:
266
+ - - ">="
267
+ - !ruby/object:Gem::Version
268
+ version: '0'
269
+ requirements: []
270
+ rubygems_version: 3.2.15
271
+ signing_key:
272
+ specification_version: 4
273
+ summary: Library for removing and clearing data in Rails ActiveRecord models.
274
+ test_files: []