Skip to content

Commit 89d6175

Browse files
committed
Let RSpec/SpecFilePathFormat leverage ActiveSupport inflections when defined and configured
Fix #740
1 parent b0fda47 commit 89d6175

File tree

4 files changed

+405
-4
lines changed

4 files changed

+405
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Master (Unreleased)
44

5+
- Let `RSpec/SpecFilePathFormat` leverage ActiveSupport inflections when configured. ([@corsonknowles])
6+
57
## 3.6.0 (2025-04-18)
68

79
- Fix false positive in `RSpec/Pending`, where it would mark the default block `it` as an offense. ([@bquorning])

config/default.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,8 @@ RSpec/SpecFilePathFormat:
924924
IgnoreMethods: false
925925
IgnoreMetadata:
926926
type: routing
927+
InflectorPath: "./config/initializers/inflections.rb"
928+
UseActiveSupportInflections: false
927929
VersionAdded: '2.24'
928930
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathFormat
929931

lib/rubocop/cop/rspec/spec_file_path_format.rb

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,22 @@ module RSpec
3232
# # good
3333
# whatever_spec.rb # describe MyClass, type: :routing do; end
3434
#
35+
# @example `UseActiveSupportInflections: true`
36+
# # Enable to use ActiveSupport's inflector for custom acronyms
37+
# # like HTTP, etc. Set to false by default.
38+
# # The InflectorPath provides the path to the inflector file.
39+
# # The default is ./config/initializers/inflections.rb.
40+
#
3541
class SpecFilePathFormat < Base
3642
include TopLevelGroup
3743
include Namespace
3844
include FileHelp
3945

4046
MSG = 'Spec path should end with `%<suffix>s`.'
4147

48+
# Class instance variable to cache ActiveSupport availability
49+
@activesupport_available = nil
50+
4251
# @!method example_group_arguments(node)
4352
def_node_matcher :example_group_arguments, <<~PATTERN
4453
(block $(send #rspec? #ExampleGroups.all $_ $...) ...)
@@ -57,6 +66,28 @@ def on_top_level_example_group(node)
5766
end
5867
end
5968

69+
# For testing and debugging
70+
def self.reset_activesupport_cache!
71+
@activesupport_available = nil
72+
end
73+
74+
def self.activesupport_inflections_available?(inflections)
75+
return @activesupport_available unless @activesupport_available.nil?
76+
77+
@activesupport_available = begin
78+
return false unless File.exist?(inflections)
79+
80+
require 'active_support/inflector'
81+
require inflections
82+
83+
true
84+
rescue LoadError, NameError
85+
false
86+
end
87+
rescue StandardError
88+
false
89+
end
90+
6091
private
6192

6293
def ensure_correct_file_path(send_node, class_name, arguments)
@@ -106,10 +137,29 @@ def expected_path(constant)
106137
end
107138

108139
def camel_to_snake_case(string)
109-
string
110-
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
111-
.gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
112-
.downcase
140+
if activesupport_inflections_available?
141+
ActiveSupport::Inflector.underscore(string)
142+
else
143+
string
144+
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
145+
.gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
146+
.downcase
147+
end
148+
end
149+
150+
def inflector_path
151+
cop_config.fetch('InflectorPath',
152+
'./config/initializers/inflections.rb')
153+
end
154+
155+
def activesupport_inflections_available?
156+
return false unless use_activesupport_inflections?
157+
158+
self.class.activesupport_inflections_available?(inflector_path)
159+
end
160+
161+
def use_activesupport_inflections?
162+
cop_config.fetch('UseActiveSupportInflections', false)
113163
end
114164

115165
def custom_transform

0 commit comments

Comments
 (0)