From 23a3862fca4ad95408178dca4efee49cc5bff6c2 Mon Sep 17 00:00:00 2001 From: Mark Maglana Date: Wed, 18 Sep 2013 00:55:24 -0700 Subject: [PATCH] Load base request class as needed --- lib/aviator/core/request_builder.rb | 81 +++++++++++++++-------- test/aviator/core/request_builder_test.rb | 19 ++++++ 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/lib/aviator/core/request_builder.rb b/lib/aviator/core/request_builder.rb index af0a083..d69114c 100644 --- a/lib/aviator/core/request_builder.rb +++ b/lib/aviator/core/request_builder.rb @@ -1,12 +1,10 @@ module Aviator class BaseRequestNotFoundError < StandardError - attr_reader :base_request_hierarchy, - :original_error + attr_reader :base_request_hierarchy - def initialize(base_hierarchy, original_error) + def initialize(base_hierarchy) @base_request_hierarchy = base_hierarchy - @original_error = original_error super("#{ base_request_hierarchy } could not be found!") end end @@ -24,39 +22,66 @@ module Aviator end - class << self + class RequestBuilder - def define_request(request_name, base_hierarchy=[:request], &block) - base_klass = base_hierarchy.inject(self) do |namespace, sym| - begin + class << self + + def define_request(root_namespace, request_name, base_hierarchy=[:request], &block) + base_klass = get_request_class(root_namespace, base_hierarchy) + + klass = Class.new(base_klass, &block) + + namespace_arr = [ + klass.provider, + klass.service, + klass.api_version, + klass.endpoint_type + ] + + namespace = namespace_arr.inject(root_namespace) do |namespace, sym| + const_name = sym.to_s.camelize + namespace.const_set(const_name, Module.new) unless namespace.const_defined?(const_name, false) + namespace.const_get(const_name, false) + end + + klassname = request_name.to_s.camelize + + if namespace.const_defined?(klassname, false) + raise RequestAlreadyDefinedError.new(namespace, klassname) + end + + namespace.const_set(klassname, klass) + end + + + def get_request_class(root_namespace, request_class_arr) + request_class_arr.inject(root_namespace) do |namespace, sym| namespace.const_get(sym.to_s.camelize, false) - rescue NameError => original_error - raise BaseRequestNotFoundError.new(base_hierarchy, original_error) + end + rescue NameError => e + arr = ['..', '..'] + request_class_arr + arr[-1,1] = arr.last.to_s + '.rb' + path = Pathname.new(__FILE__).join(*arr.map{|i| i.to_s }).expand_path + + if path.exist? + require path + request_class_arr.inject(root_namespace) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + else + raise BaseRequestNotFoundError.new(request_class_arr) end end - klass = Class.new(base_klass, &block) + end - namespace_arr = [ - klass.provider, - klass.service, - klass.api_version, - klass.endpoint_type - ] + end - namespace = namespace_arr.inject(self) do |namespace, sym| - const_name = sym.to_s.camelize - namespace.const_set(const_name, Module.new) unless namespace.const_defined?(const_name, false) - namespace.const_get(const_name, false) - end - klassname = request_name.to_s.camelize + class << self - if namespace.const_defined?(klassname, false) - raise RequestAlreadyDefinedError.new(namespace, klassname) - end - - namespace.const_set(klassname, klass) + def define_request(request_name, base_hierarchy=[:request], &block) + RequestBuilder.define_request self, request_name, base_hierarchy, &block end end # class << self diff --git a/test/aviator/core/request_builder_test.rb b/test/aviator/core/request_builder_test.rb index fa0f6f9..16f974f 100644 --- a/test/aviator/core/request_builder_test.rb +++ b/test/aviator/core/request_builder_test.rb @@ -156,6 +156,25 @@ class Aviator::Test error.request_name.must_equal request[:name].to_s.camelize end + + it 'automatically attempts to load the base class if it\'s not yet loaded' do + base_arr = [:openstack, :identity, :v2, :public, :root] + child_arr = base_arr.first(base_arr.length - 1) + [:child] + + builder.define_request child_arr.last, base_arr do; end + + base_klass = base_arr.inject(builder) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + + child_klass = child_arr.inject(builder) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + + base_klass.wont_be_nil + child_klass.wont_be_nil + end + end end