rubocop-rails 2.20.2 → 2.25.0

Sign up to get free protection for your applications and to get access to all the features.
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.