Class: Jets::Klass
- Inherits:
-
Object
- Object
- Jets::Klass
- Defined in:
- lib/jets/klass.rb
Overview
Loading a class can usually be loaded via .constantize. But app/functions files are anonymous ruby classes created with Class.new. Anonymous classes cannot be loaded via .constantize and go through standard autoloading.
Jets::Klass provides a way to load app classes in app/controllers, app/jobs, app/functions in a consistent way without having to worry about the anonymous class loading quirk. Classes that are not anonymously defined like controllers and jobs are loaded via autoloading with .constantize. Anonymously defined classes like functions are loaded via Object.const_set.
Examples:
Jets::Klass.from_path("app/controllers/posts_controller.rb")
Jets::Klass.from_path("app/jobs/hard_job.rb")
Jets::Klass.from_path("app/functions/hello.rb")
Jets::Klass.from_path("app/functions/hello_function.rb")
Jets::Klass.from_path("app/shared/functions/whatever.rb")
Jets::Klass.from_task(task)
The from_task method takes a Jets::Lambda::Task as an argument and is useful for the CloudFormation child stack generation there the registered task info is available but the path info is now.
Constant Summary collapse
- APP_TYPES =
%w[controller job rule authorizer]
- @@loaded_anonymous_classes =
[]
Class Method Summary collapse
-
.class_name(path) ⇒ Object
app/controllers/posts_controller.rb => PostsController.
-
.from_path(path) ⇒ Object
from_path allows us to load any app classes in consistent way for app/controllers, app/jobs, and app/functions.
- .from_task(task) ⇒ Object
- .load_anonymous_class(class_name, path) ⇒ Object
-
.modularize(class_name) ⇒ Object
Ensures the parent namespace modules are defined.
Class Method Details
.class_name(path) ⇒ Object
app/controllers/posts_controller.rb => PostsController
40 41 42 43 44 45 46 |
# File 'lib/jets/klass.rb', line 40 def class_name(path) if path.include?("/shared/") path.sub(%r{.*app/shared/(.*?)/},'').sub(/\.rb$/,'').camelize else path.sub(%r{.*app/(.*?)/},'').sub(/\.rb$/,'').camelize end end |
.from_path(path) ⇒ Object
from_path allows us to load any app classes in consistent way for app/controllers, app/jobs, and app/functions.
29 30 31 32 33 34 35 36 37 |
# File 'lib/jets/klass.rb', line 29 def from_path(path) class_name = class_name(path) if path.include?("/functions/") # simple function class_name = load_anonymous_class(class_name, path) class_name.constantize # removed :: for anonymous classes else class_name.constantize # autoload end end |
.from_task(task) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/jets/klass.rb', line 49 def from_task(task) class_name = task.class_name filename = class_name.underscore # Examples of filename: posts_controller, hard_job, security_rule, main_authorizer # hello_function, hello type = filename.split('_').last type = "function" unless APP_TYPES.include?(type) path = "app/#{type.pluralize}/#{filename}.rb" from_path(path) end |
.load_anonymous_class(class_name, path) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/jets/klass.rb', line 63 def load_anonymous_class(class_name, path) parent_mod = modularize(class_name) constructor = Jets::Lambda::FunctionConstructor.new(path) # Dont load anonyomous class more than once to avoid these warnings: # warning: already initialized constant Hello # warning: previous definition of Hello was here unless @@loaded_anonymous_classes.include?(class_name) # use class_name as the variable name for prettier class name. leaf_class_name = class_name.split('::').last parent_mod.const_set(leaf_class_name, constructor.build) @@loaded_anonymous_classes << class_name end class_name end |
.modularize(class_name) ⇒ Object
Ensures the parent namespace modules are defined. Example:
modularize("Foo::Bar::Test")
=> Foo::Bar # is a now defined as a module if it wasnt before
Also returns the parent module, so we can use it to do a const_set if needed. IE:
parent_mod = modularize("Foo::Bar::Test")
parent_mod.const_set("Test")
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/jets/klass.rb', line 89 def modularize(class_name) leaves = [] mods = class_name.split('::')[0..-2] # drop the last word # puts "mods: #{mods}" return Object if mods.empty? leaves = [] mods.each do |leaf_mod| leaves += [leaf_mod] namespace = leaves.join('::') previous_namespace = leaves[0..-2].join('::') previous_namespace = "Object" if previous_namespace.empty? previous_namespace = previous_namespace.constantize previous_namespace.const_set(leaf_mod, Module.new) unless Object.const_defined?(namespace) end mods.join('::').constantize end |