class ApiVersioning class Middleware def initialize(app) @app = app end def call(env) if version_number = extract_version_number(env) ApiVersioning.current_version_number = version_number.to_i Rails.application.eager_load! unless Rails.application.config.cache_classes ClassDescendantsBuilder.build ApiBeta::ApplicationController, ApiVersioning.max_version_number end @app.call env end private def extract_version_number(env) env['HTTP_ACCEPT'] && env['HTTP_ACCEPT'][/v([0-9\.]+)\+json/, 1] end end class_attribute :current_version_number def self.instance @instance || raise('call `.setup` first') end def self.setup(context, &block) @instance = new(context, &block) end def self.min_version_number instance.min_version_number end def self.max_version_number instance.max_version_number end def initialize(context, &block) @context, @definitions = context, {} instance_eval &block end def version(number, &block) @definitions[number] = block || Proc.new {} @context.scope module: "v#{number}", constraints: ->(*) { ApiVersioning.current_version_number == number } do number.downto(min_version_number) do |i| @context.instance_eval &@definitions[i] end end end def min_version_number @definitions.keys.min end def max_version_number @definitions.keys.max end end