Created
April 20, 2022 16:26
-
-
Save estum/5a69fad6db9a914bf8ec69ad8d41371b to your computer and use it in GitHub Desktop.
Mixin with namespaced macro to inherit view prefixes from several modules.
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
# Mixin with namespaced macro to inherit view prefixes from several modules. | |
# | |
# @example Imagine legacy controllers… | |
# module V1 | |
# class BaseController < ActionController::Metal; end | |
# # => _prefixes: ['api/v1/base'] | |
# | |
# class PostsController < BaseController; end | |
# # => _prefixes: ['api/v1/base', 'api/v1/posts'] | |
# end | |
# | |
# @example …and inherited actual version | |
# module V2 | |
# class PostsController < V1::PostsController; end | |
# # => _prefixes: ['v1/base', 'v1/posts', 'v2/posts'] | |
# end | |
# | |
# @example Extend namespace with SumsPrefix, if it's wanted to include 'v2/base' in the view prefixes of V2::PostsController! | |
# module V2 | |
# extend SumsPrefix | |
# | |
# class BaseController < V1::BaseController; end | |
# # => _prefixes: ['v1/base', 'v2/base'] | |
# | |
# class PostsController < Sum(V1::PostsController, BaseController); end | |
# # => _prefixes: ['v1/base', 'v1/posts', 'v2/base', 'v2/posts'] | |
# end | |
module SumsPrefix | |
NAME_TEMPLATE = 'Sum_%sController' | |
private | |
# @!visibility public | |
# @overload Sum(parent, *rest) | |
# Hooks the given class with view prefixes from parents | |
# @param parent [Class] class to inherit | |
# @param rest [Array<Class>] classes to include prefixes from | |
# @return [Class] | |
# a middleware controller inherited from a +parent+ class and | |
# defined in the caller's namespace with name template {NAME_TEMPLATE} | |
def Sum(*parents) | |
@sumed_classes = Concurrent::Map.new unless defined?(@sumed_classes) | |
@sumed_classes.fetch_or_store(parents.hash) do | |
parent, *rest = parents | |
const_name = (NAME_TEMPLATE % parents.map(&:controller_name).join(?_).classify).to_sym | |
sumed = const_set(const_name, Class.new(parent)) | |
prefixes = rest.inject(parent._prefixes) { |a, e| (e._prefixes - a) + a } | |
sumed.instance_variable_set(:@_prefixes, prefixes) | |
sumed | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment