require 'active_support/concern' module Machined # Initializable is a minimal version of # Rails::Initializable. Its implementation # of placing initializers before or after other # initializers is a bit naive, compared to the Rails # version, but it suits the needs of this lib. # # If they move Rails::Initializable into ActiveSupport # I'll remove this module and use theirs. Right now, # I don't want to `require 'rails'` if I don't have to. module Initializable extend ActiveSupport::Concern class Initializer < Struct.new(:name, :block) # Run's the initializer's +block+ with the given # +context+ and yields the given +args+ # to the block. def run(context, *args) context.instance_exec(*args, &block) end end module ClassMethods # Returns an array of the initializers for # this class. def initializers @initializers ||= [] end # Creates a new initializer with the given name. # You can optionally pace initializers before or after # other initializers using the `:before` and `:after` # options. Otherwise the initializer is appended to the # of the list. def initializer(name, options = {}, &block) initializer = Initializer.new(name, block) if after = options[:after] initializers.insert initializer_index(after) + 1, initializer elsif before = options[:before] initializers.insert initializer_index(before), initializer else initializers << initializer end end protected # Returns the index of the initializer with # the given name. def initializer_index(name) # :nodoc: initializers.index do |initializer| initializer.name.to_sym == name.to_sym end or raise "The specified initializer, #{name.inspect}, does not exist" end end # Run each initializer with the given args # yielded to each initializer's block. def run_initializers(*args) # return if @initializers_run self.class.initializers.each do |initializer| initializer.run self, *args end # @initializers_run = true end end end