rubocop-rails 2.20.2 → 2.25.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -7
  3. data/config/default.yml +81 -12
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +15 -3
  5. data/lib/rubocop/cop/mixin/database_type_resolvable.rb +66 -0
  6. data/lib/rubocop/cop/mixin/index_method.rb +2 -2
  7. data/lib/rubocop/cop/mixin/target_rails_version.rb +29 -2
  8. data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +3 -1
  9. data/lib/rubocop/cop/rails/action_controller_test_case.rb +2 -2
  10. data/lib/rubocop/cop/rails/action_filter.rb +3 -0
  11. data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -2
  12. data/lib/rubocop/cop/rails/active_support_aliases.rb +6 -5
  13. data/lib/rubocop/cop/rails/active_support_on_load.rb +21 -1
  14. data/lib/rubocop/cop/rails/after_commit_override.rb +1 -1
  15. data/lib/rubocop/cop/rails/bulk_change_table.rb +8 -41
  16. data/lib/rubocop/cop/rails/content_tag.rb +1 -1
  17. data/lib/rubocop/cop/rails/dangerous_column_names.rb +446 -0
  18. data/lib/rubocop/cop/rails/date.rb +1 -1
  19. data/lib/rubocop/cop/rails/duplicate_association.rb +69 -12
  20. data/lib/rubocop/cop/rails/dynamic_find_by.rb +3 -3
  21. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +2 -2
  22. data/lib/rubocop/cop/rails/env_local.rb +46 -0
  23. data/lib/rubocop/cop/rails/expanded_date_range.rb +1 -1
  24. data/lib/rubocop/cop/rails/file_path.rb +9 -6
  25. data/lib/rubocop/cop/rails/find_by.rb +3 -3
  26. data/lib/rubocop/cop/rails/find_by_id.rb +9 -23
  27. data/lib/rubocop/cop/rails/freeze_time.rb +1 -1
  28. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -1
  29. data/lib/rubocop/cop/rails/helper_instance_variable.rb +1 -1
  30. data/lib/rubocop/cop/rails/http_status.rb +16 -5
  31. data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +63 -13
  32. data/lib/rubocop/cop/rails/inquiry.rb +1 -0
  33. data/lib/rubocop/cop/rails/inverse_of.rb +1 -1
  34. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +7 -8
  35. data/lib/rubocop/cop/rails/not_null_column.rb +94 -6
  36. data/lib/rubocop/cop/rails/output.rb +3 -2
  37. data/lib/rubocop/cop/rails/pick.rb +10 -5
  38. data/lib/rubocop/cop/rails/pluck.rb +1 -1
  39. data/lib/rubocop/cop/rails/pluck_id.rb +2 -1
  40. data/lib/rubocop/cop/rails/pluck_in_where.rb +18 -5
  41. data/lib/rubocop/cop/rails/rake_environment.rb +22 -6
  42. data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +219 -0
  43. data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +7 -0
  44. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
  45. data/lib/rubocop/cop/rails/response_parsed_body.rb +52 -10
  46. data/lib/rubocop/cop/rails/reversible_migration.rb +4 -4
  47. data/lib/rubocop/cop/rails/root_pathname_methods.rb +38 -4
  48. data/lib/rubocop/cop/rails/save_bang.rb +15 -8
  49. data/lib/rubocop/cop/rails/schema_comment.rb +16 -10
  50. data/lib/rubocop/cop/rails/select_map.rb +78 -0
  51. data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -1
  52. data/lib/rubocop/cop/rails/time_zone.rb +13 -5
  53. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +29 -10
  54. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +12 -4
  55. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +2 -2
  56. data/lib/rubocop/cop/rails/unknown_env.rb +5 -1
  57. data/lib/rubocop/cop/rails/unused_ignored_columns.rb +6 -0
  58. data/lib/rubocop/cop/rails/unused_render_content.rb +67 -0
  59. data/lib/rubocop/cop/rails/validation.rb +6 -4
  60. data/lib/rubocop/cop/rails/where_equals.rb +3 -2
  61. data/lib/rubocop/cop/rails/where_exists.rb +9 -9
  62. data/lib/rubocop/cop/rails/where_missing.rb +6 -2
  63. data/lib/rubocop/cop/rails/where_not.rb +8 -6
  64. data/lib/rubocop/cop/rails/where_range.rb +157 -0
  65. data/lib/rubocop/cop/rails_cops.rb +7 -0
  66. data/lib/rubocop/rails/schema_loader/schema.rb +3 -2
  67. data/lib/rubocop/rails/schema_loader.rb +5 -15
  68. data/lib/rubocop/rails/version.rb +1 -1
  69. data/lib/rubocop-rails.rb +8 -0
  70. metadata +31 -4
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Identifies places where manually constructed SQL
7
+ # in `where` can be replaced with ranges.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # User.where('age >= ?', 18)
12
+ # User.where.not('age >= ?', 18)
13
+ # User.where('age < ?', 18)
14
+ # User.where('age >= ? AND age < ?', 18, 21)
15
+ # User.where('age >= :start', start: 18)
16
+ # User.where('users.age >= ?', 18)
17
+ #
18
+ # # good
19
+ # User.where(age: 18..)
20
+ # User.where.not(age: 18..)
21
+ # User.where(age: ...18)
22
+ # User.where(age: 18...21)
23
+ # User.where(users: { age: 18.. })
24
+ #
25
+ # # good
26
+ # # There are no beginless ranges in ruby.
27
+ # User.where('age > ?', 18)
28
+ #
29
+ class WhereRange < Base
30
+ include RangeHelp
31
+ extend AutoCorrector
32
+ extend TargetRubyVersion
33
+ extend TargetRailsVersion
34
+
35
+ MSG = 'Use `%<good_method>s` instead of manually constructing SQL.'
36
+
37
+ RESTRICT_ON_SEND = %i[where not].freeze
38
+
39
+ # column >= ?
40
+ GTEQ_ANONYMOUS_RE = /\A([\w.]+)\s+>=\s+\?\z/.freeze
41
+ # column <[=] ?
42
+ LTEQ_ANONYMOUS_RE = /\A([\w.]+)\s+(<=?)\s+\?\z/.freeze
43
+ # column >= ? AND column <[=] ?
44
+ RANGE_ANONYMOUS_RE = /\A([\w.]+)\s+>=\s+\?\s+AND\s+\1\s+(<=?)\s+\?\z/i.freeze
45
+ # column >= :value
46
+ GTEQ_NAMED_RE = /\A([\w.]+)\s+>=\s+:(\w+)\z/.freeze
47
+ # column <[=] :value
48
+ LTEQ_NAMED_RE = /\A([\w.]+)\s+(<=?)\s+:(\w+)\z/.freeze
49
+ # column >= :value1 AND column <[=] :value2
50
+ RANGE_NAMED_RE = /\A([\w.]+)\s+>=\s+:(\w+)\s+AND\s+\1\s+(<=?)\s+:(\w+)\z/i.freeze
51
+
52
+ minimum_target_ruby_version 2.6
53
+ minimum_target_rails_version 6.0
54
+
55
+ def_node_matcher :where_range_call?, <<~PATTERN
56
+ {
57
+ (call _ {:where :not} (array $str_type? $_ +))
58
+ (call _ {:where :not} $str_type? $_ +)
59
+ }
60
+ PATTERN
61
+
62
+ def on_send(node)
63
+ return if node.method?(:not) && !where_not?(node)
64
+
65
+ where_range_call?(node) do |template_node, values_node|
66
+ column, value = extract_column_and_value(template_node, values_node)
67
+
68
+ return unless column
69
+
70
+ range = offense_range(node)
71
+ good_method = build_good_method(node.method_name, column, value)
72
+ message = format(MSG, good_method: good_method)
73
+
74
+ add_offense(range, message: message) do |corrector|
75
+ corrector.replace(range, good_method)
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def where_not?(node)
83
+ receiver = node.receiver
84
+ receiver&.send_type? && receiver&.method?(:where)
85
+ end
86
+
87
+ # rubocop:disable Metrics
88
+ def extract_column_and_value(template_node, values_node)
89
+ value =
90
+ case template_node.value
91
+ when GTEQ_ANONYMOUS_RE
92
+ "#{values_node[0].source}.."
93
+ when LTEQ_ANONYMOUS_RE
94
+ range_operator = range_operator(Regexp.last_match(2))
95
+ "#{range_operator}#{values_node[0].source}" if target_ruby_version >= 2.7
96
+ when RANGE_ANONYMOUS_RE
97
+ if values_node.size >= 2
98
+ range_operator = range_operator(Regexp.last_match(2))
99
+ "#{values_node[0].source}#{range_operator}#{values_node[1].source}"
100
+ end
101
+ when GTEQ_NAMED_RE
102
+ value_node = values_node[0]
103
+
104
+ if value_node.hash_type?
105
+ pair = find_pair(value_node, Regexp.last_match(2))
106
+ "#{pair.value.source}.." if pair
107
+ end
108
+ when LTEQ_NAMED_RE
109
+ value_node = values_node[0]
110
+
111
+ if value_node.hash_type?
112
+ pair = find_pair(value_node, Regexp.last_match(2))
113
+ if pair && target_ruby_version >= 2.7
114
+ range_operator = range_operator(Regexp.last_match(2))
115
+ "#{range_operator}#{pair.value.source}"
116
+ end
117
+ end
118
+ when RANGE_NAMED_RE
119
+ value_node = values_node[0]
120
+
121
+ if value_node.hash_type?
122
+ range_operator = range_operator(Regexp.last_match(3))
123
+ pair1 = find_pair(value_node, Regexp.last_match(2))
124
+ pair2 = find_pair(value_node, Regexp.last_match(4))
125
+ "#{pair1.value.source}#{range_operator}#{pair2.value.source}" if pair1 && pair2
126
+ end
127
+ end
128
+
129
+ [Regexp.last_match(1), value] if value
130
+ end
131
+ # rubocop:enable Metrics
132
+
133
+ def range_operator(comparison_operator)
134
+ comparison_operator == '<' ? '...' : '..'
135
+ end
136
+
137
+ def find_pair(hash_node, value)
138
+ hash_node.pairs.find { |pair| pair.key.value.to_sym == value.to_sym }
139
+ end
140
+
141
+ def offense_range(node)
142
+ range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
143
+ end
144
+
145
+ def build_good_method(method_name, column, value)
146
+ if column.include?('.')
147
+ table, column = column.split('.')
148
+
149
+ "#{method_name}(#{table}: { #{column}: #{value} })"
150
+ else
151
+ "#{method_name}(#{column}: #{value})"
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -3,6 +3,7 @@
3
3
  require_relative 'mixin/active_record_helper'
4
4
  require_relative 'mixin/active_record_migrations_helper'
5
5
  require_relative 'mixin/class_send_node_helper'
6
+ require_relative 'mixin/database_type_resolvable'
6
7
  require_relative 'mixin/enforce_superclass'
7
8
  require_relative 'mixin/index_method'
8
9
  require_relative 'mixin/migrations_helper'
@@ -32,6 +33,7 @@ require_relative 'rails/bulk_change_table'
32
33
  require_relative 'rails/compact_blank'
33
34
  require_relative 'rails/content_tag'
34
35
  require_relative 'rails/create_table_with_timestamps'
36
+ require_relative 'rails/dangerous_column_names'
35
37
  require_relative 'rails/date'
36
38
  require_relative 'rails/default_scope'
37
39
  require_relative 'rails/delegate'
@@ -45,6 +47,7 @@ require_relative 'rails/dynamic_find_by'
45
47
  require_relative 'rails/eager_evaluation_log_message'
46
48
  require_relative 'rails/enum_hash'
47
49
  require_relative 'rails/enum_uniqueness'
50
+ require_relative 'rails/env_local'
48
51
  require_relative 'rails/environment_comparison'
49
52
  require_relative 'rails/environment_variable_access'
50
53
  require_relative 'rails/exit'
@@ -87,6 +90,7 @@ require_relative 'rails/presence'
87
90
  require_relative 'rails/present'
88
91
  require_relative 'rails/rake_environment'
89
92
  require_relative 'rails/read_write_attribute'
93
+ require_relative 'rails/redundant_active_record_all_method'
90
94
  require_relative 'rails/redundant_allow_nil'
91
95
  require_relative 'rails/redundant_foreign_key'
92
96
  require_relative 'rails/redundant_presence_validation_on_belongs_to'
@@ -110,6 +114,7 @@ require_relative 'rails/safe_navigation_with_blank'
110
114
  require_relative 'rails/save_bang'
111
115
  require_relative 'rails/schema_comment'
112
116
  require_relative 'rails/scope_args'
117
+ require_relative 'rails/select_map'
113
118
  require_relative 'rails/short_i18n'
114
119
  require_relative 'rails/skips_model_validations'
115
120
  require_relative 'rails/squished_sql_heredocs'
@@ -126,9 +131,11 @@ require_relative 'rails/uniq_before_pluck'
126
131
  require_relative 'rails/unique_validation_without_index'
127
132
  require_relative 'rails/unknown_env'
128
133
  require_relative 'rails/unused_ignored_columns'
134
+ require_relative 'rails/unused_render_content'
129
135
  require_relative 'rails/validation'
130
136
  require_relative 'rails/where_equals'
131
137
  require_relative 'rails/where_exists'
132
138
  require_relative 'rails/where_missing'
133
139
  require_relative 'rails/where_not'
134
140
  require_relative 'rails/where_not_with_multiple_conditions'
141
+ require_relative 'rails/where_range'
@@ -30,6 +30,7 @@ module RuboCop
30
30
 
31
31
  def build!(ast)
32
32
  raise "Unexpected type: #{ast.type}" unless ast.block_type?
33
+ return unless ast.body
33
34
 
34
35
  each_table(ast) do |table_def|
35
36
  next unless table_def.method?(:create_table)
@@ -127,7 +128,7 @@ module RuboCop
127
128
  private
128
129
 
129
130
  def analyze_keywords!(node)
130
- pairs = node.arguments.last
131
+ pairs = node.last_argument
131
132
  return unless pairs.hash_type?
132
133
 
133
134
  pairs.each_pair do |k, v|
@@ -158,7 +159,7 @@ module RuboCop
158
159
  end
159
160
 
160
161
  def analyze_keywords!(node)
161
- pairs = node.arguments.last
162
+ pairs = node.last_argument
162
163
  return unless pairs.hash_type?
163
164
 
164
165
  pairs.each_pair do |k, v|
@@ -12,10 +12,10 @@ module RuboCop
12
12
  # So a cop that uses the loader should handle `nil` properly.
13
13
  #
14
14
  # @return [Schema, nil]
15
- def load(target_ruby_version)
15
+ def load(target_ruby_version, parser_engine)
16
16
  return @load if defined?(@load)
17
17
 
18
- @load = load!(target_ruby_version)
18
+ @load = load!(target_ruby_version, parser_engine)
19
19
  end
20
20
 
21
21
  def reset!
@@ -38,23 +38,13 @@ module RuboCop
38
38
 
39
39
  private
40
40
 
41
- def load!(target_ruby_version)
41
+ def load!(target_ruby_version, parser_engine)
42
42
  path = db_schema_path
43
43
  return unless path
44
44
 
45
- ast = parse(path, target_ruby_version)
46
- Schema.new(ast)
47
- end
48
-
49
- def parse(path, target_ruby_version)
50
- klass_name = :"Ruby#{target_ruby_version.to_s.sub('.', '')}"
51
- klass = ::Parser.const_get(klass_name)
52
- parser = klass.new(RuboCop::AST::Builder.new)
53
-
54
- buffer = Parser::Source::Buffer.new(path, 1)
55
- buffer.source = path.read
45
+ ast = RuboCop::ProcessedSource.new(File.read(path), target_ruby_version, path, parser_engine: parser_engine).ast
56
46
 
57
- parser.parse(buffer)
47
+ Schema.new(ast) if ast
58
48
  end
59
49
  end
60
50
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Rails
5
5
  # This module holds the RuboCop Rails version information.
6
6
  module Version
7
- STRING = '2.20.2'
7
+ STRING = '2.25.0'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
data/lib/rubocop-rails.rb CHANGED
@@ -17,6 +17,14 @@ require_relative 'rubocop/cop/rails_cops'
17
17
 
18
18
  RuboCop::Cop::Style::HashExcept.minimum_target_ruby_version(2.0)
19
19
 
20
+ RuboCop::Cop::Style::InverseMethods.singleton_class.prepend(
21
+ Module.new do
22
+ def autocorrect_incompatible_with
23
+ super.push(RuboCop::Cop::Rails::NegateInclude)
24
+ end
25
+ end
26
+ )
27
+
20
28
  RuboCop::Cop::Style::MethodCallWithArgsParentheses.singleton_class.prepend(
21
29
  Module.new do
22
30
  def autocorrect_incompatible_with
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.20.2
4
+ version: 2.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-06-19 00:00:00.000000000 Z
13
+ date: 2024-05-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -60,6 +60,26 @@ dependencies:
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '2.0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rubocop-ast
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 1.31.1
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '2.0'
73
+ type: :runtime
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 1.31.1
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
63
83
  description: |
64
84
  Automatic Rails code style checking tool.
65
85
  A RuboCop extension focused on enforcing Rails best practices and coding conventions.
@@ -78,6 +98,7 @@ files:
78
98
  - lib/rubocop/cop/mixin/active_record_helper.rb
79
99
  - lib/rubocop/cop/mixin/active_record_migrations_helper.rb
80
100
  - lib/rubocop/cop/mixin/class_send_node_helper.rb
101
+ - lib/rubocop/cop/mixin/database_type_resolvable.rb
81
102
  - lib/rubocop/cop/mixin/enforce_superclass.rb
82
103
  - lib/rubocop/cop/mixin/index_method.rb
83
104
  - lib/rubocop/cop/mixin/migrations_helper.rb
@@ -106,6 +127,7 @@ files:
106
127
  - lib/rubocop/cop/rails/compact_blank.rb
107
128
  - lib/rubocop/cop/rails/content_tag.rb
108
129
  - lib/rubocop/cop/rails/create_table_with_timestamps.rb
130
+ - lib/rubocop/cop/rails/dangerous_column_names.rb
109
131
  - lib/rubocop/cop/rails/date.rb
110
132
  - lib/rubocop/cop/rails/default_scope.rb
111
133
  - lib/rubocop/cop/rails/delegate.rb
@@ -119,6 +141,7 @@ files:
119
141
  - lib/rubocop/cop/rails/eager_evaluation_log_message.rb
120
142
  - lib/rubocop/cop/rails/enum_hash.rb
121
143
  - lib/rubocop/cop/rails/enum_uniqueness.rb
144
+ - lib/rubocop/cop/rails/env_local.rb
122
145
  - lib/rubocop/cop/rails/environment_comparison.rb
123
146
  - lib/rubocop/cop/rails/environment_variable_access.rb
124
147
  - lib/rubocop/cop/rails/exit.rb
@@ -161,6 +184,7 @@ files:
161
184
  - lib/rubocop/cop/rails/present.rb
162
185
  - lib/rubocop/cop/rails/rake_environment.rb
163
186
  - lib/rubocop/cop/rails/read_write_attribute.rb
187
+ - lib/rubocop/cop/rails/redundant_active_record_all_method.rb
164
188
  - lib/rubocop/cop/rails/redundant_allow_nil.rb
165
189
  - lib/rubocop/cop/rails/redundant_foreign_key.rb
166
190
  - lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb
@@ -184,6 +208,7 @@ files:
184
208
  - lib/rubocop/cop/rails/save_bang.rb
185
209
  - lib/rubocop/cop/rails/schema_comment.rb
186
210
  - lib/rubocop/cop/rails/scope_args.rb
211
+ - lib/rubocop/cop/rails/select_map.rb
187
212
  - lib/rubocop/cop/rails/short_i18n.rb
188
213
  - lib/rubocop/cop/rails/skips_model_validations.rb
189
214
  - lib/rubocop/cop/rails/squished_sql_heredocs.rb
@@ -200,12 +225,14 @@ files:
200
225
  - lib/rubocop/cop/rails/unique_validation_without_index.rb
201
226
  - lib/rubocop/cop/rails/unknown_env.rb
202
227
  - lib/rubocop/cop/rails/unused_ignored_columns.rb
228
+ - lib/rubocop/cop/rails/unused_render_content.rb
203
229
  - lib/rubocop/cop/rails/validation.rb
204
230
  - lib/rubocop/cop/rails/where_equals.rb
205
231
  - lib/rubocop/cop/rails/where_exists.rb
206
232
  - lib/rubocop/cop/rails/where_missing.rb
207
233
  - lib/rubocop/cop/rails/where_not.rb
208
234
  - lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb
235
+ - lib/rubocop/cop/rails/where_range.rb
209
236
  - lib/rubocop/cop/rails_cops.rb
210
237
  - lib/rubocop/rails.rb
211
238
  - lib/rubocop/rails/inject.rb
@@ -219,7 +246,7 @@ metadata:
219
246
  homepage_uri: https://docs.rubocop.org/rubocop-rails/
220
247
  changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
221
248
  source_code_uri: https://github.com/rubocop/rubocop-rails/
222
- documentation_uri: https://docs.rubocop.org/rubocop-rails/2.20/
249
+ documentation_uri: https://docs.rubocop.org/rubocop-rails/2.25/
223
250
  bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
224
251
  rubygems_mfa_required: 'true'
225
252
  post_install_message:
@@ -237,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
264
  - !ruby/object:Gem::Version
238
265
  version: '0'
239
266
  requirements: []
240
- rubygems_version: 3.5.0.dev
267
+ rubygems_version: 3.5.3
241
268
  signing_key:
242
269
  specification_version: 4
243
270
  summary: Automatic Rails code style checking tool.