Created
October 16, 2023 20:18
-
-
Save caius/12efec822b0c4cb96bfa39d78f7096a8 to your computer and use it in GitHub Desktop.
Zeitwerk Inflector for full path -> Constant
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# Custom inflector for Zeitwerk | |
# | |
# The default inflector at ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector only | |
# lets us override by `basename`, but we have both `Thing` and `THING` defined as constants | |
# in the app so that doesn't work for us. Rather than rename everything just now, work around it | |
# by letting us define overrides by _filepath_ (`abspath`) as well as `basename`. | |
# | |
# NB: Normally we'd subclass the default implementation, but it's a Module so can't do that. | |
# | |
# @see Zeitwerk::Inflector | |
# @see ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector | |
# | |
class OurInflector | |
def initialize | |
@basename_overrides = {} | |
@relpath_overrides = {} | |
end | |
# Override constant inflections based on the basename | |
# | |
# basename is just snake_case. Basically lets you override the same snake_case to SnakeCASE | |
# across the app, no matter the namespace it's in. | |
# | |
# @param inflections [Hash{String => String}] mappings from base_name to BaseName | |
# @return [void] | |
def inflect_basename(inflections) | |
@basename_overrides.merge!(inflections) | |
end | |
# Override constant inflections based on filename in app | |
# | |
# Where we have the same downcased string resolving to two different constant names within | |
# the app we can't use `inflect_basename`. At that point we can define inflections on a file | |
# by file basis to let us override in one case. | |
# | |
# @param inflections [Hash{String => String}] mappings from relative paths to Constants | |
# @return [void] | |
def inflect_relpath(inflections) | |
@relpath_overrides.merge!(inflections) | |
end | |
# For a given basename & absolute path, return the expected constant | |
# | |
# We check for overrides in the following order: | |
# - path override | |
# - basename override | |
# - ActiveSupport camelize, which uses the app defined inflections | |
# | |
# @return [String] expected constant name as string | |
def camelize(basename, abspath) | |
relpath = abspath.sub("#{Rails.root}/", "") # rubocop:disable Rails/FilePath | |
@relpath_overrides[relpath] || @basename_overrides[basename] || basename.camelize | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment