Created
December 27, 2022 14:31
-
-
Save kaspth/6f74f670d689896c696743a69bca1719 to your computer and use it in GitHub Desktop.
Rewrite of https://github.com/rails/rails/blob/9f141a423d551f7f421f54d1372e65ef6ed1f0be/railties/lib/rails/initializable.rb for fun
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
require "tsort" | |
module Rails | |
module Initializable | |
extend ActiveSupport::Concern | |
def run_initializers(group = :default, *arguments) | |
@ran ||= true.tap do | |
Initializer.tsort(initializers).each { instance_exec(*arguments, &_1.block) if _1.in?(group) } | |
end | |
end | |
def initializers | |
self.class.ancestors.reverse.flat_map { _1.initializers if _1.respond_to?(:initializers) } | |
end | |
class_methods do | |
def initializer(name, group: :default, before: nil, after: nil, &block) | |
raise ArgumentError, "A block must be passed when defining an initializer" unless block | |
after ||= initializers.last&.name unless initializers.any? { _1.name == before } | |
initializers << Initializer.new(name:, block:, group:, before:, after:) | |
end | |
def initializers = @initializers ||= [] | |
end | |
class Initializer < Struct.new(:name, :block, :group, :before, :after, keyword_init: true) | |
def initialize(name:, block:, group: :default, before: nil, after: nil) = super | |
def self.tsort(initializers) | |
TSort.tsort initializers.to_enum, | |
->(initializer, &block) { initializer.pluck(initializers).each(&block) } | |
end | |
def pluck(initializers) | |
initializers.select { _1.before == name || after == _1.name } | |
end | |
# Alternative to pluck above to try to name, but the original inner select makes no sense to me. | |
def around?(other) = self < other || self > other | |
def >(other) = other.before == name | |
def <(other) = after == other.name | |
def in?(group) | |
@group == group || @group == :all | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment