module Vedeu # Stores all client application controllers with their respective actions. # module Router include Vedeu::Common extend self # Registers a controller with the given controller name for the client # application. # # @param controller [Symbol] # @param klass [String] # @raise [Vedeu::MissingRequired] When the controller name is not given. # @return [void] def add_controller(controller, klass) unless present?(controller) fail Vedeu::MissingRequired, 'Cannot store controller without a name attribute.' end Vedeu.log(type: :create, message: "Adding ':#{controller}'") if registered?(controller) storage[controller].merge!(klass: klass) else storage.store(controller, klass: klass, actions: []) end storage end # Registers an action to the given controller name for the client # application. # # @param controller [Symbol] # @param action [Symbol] # @raise [Vedeu::MissingRequired] When the controller name or action name is # not given. # @return [void] def add_action(controller, action) if present?(controller) && present?(action) Vedeu.log(type: :create, message: "Adding ':#{action}' for ':#{controller}'") if registered?(controller) storage[controller][:actions] << action else add_controller(controller, '') add_action(controller, action) end storage else fail Vedeu::MissingRequired, 'Cannot store action without a controller or name attribute.' end end # Instruct Vedeu to load the client application controller action with # parameters. # # @example # Vedeu.goto(controller, action, args) # # @param controller [Symbol] # @param action [Symbol] # @param args [void] # @raise [Vedeu::ModelNotFound] When the controller is not registered. # @return [void] def goto(controller, action, **args) Vedeu.log(type: :debug, message: "Routing: #{controller} #{action}") route(controller, action, args) if action_defined?(action, controller) end alias_method :action, :goto # Returns a boolean indicating whether the given controller name is already # registered. # # @param controller [Symbol] # @return [Boolean] def registered?(controller) storage.key?(controller) end # Removes all stored controllers with their respective actions. # # @return [Hash] def reset! @storage = in_memory end alias_method :reset, :reset! private # Returns a boolean indicating whether the given action name is defined for # the given controller. # # @param action [Symbol] # @param controller [Symbol] # @return [Boolean] def action_defined?(action, controller) if registered?(controller) return true if storage[controller][:actions].include?(action) fail Vedeu::ActionNotFound, "#{action} is not registered for #{controller}." else fail Vedeu::ControllerNotFound, "#{controller} is not registered." end end # Instantiate the given controller by name, the call the action (method) # with any given arguments. # # @param controller [Symbol] # @param action [Symbol] # @param args [Symbol] # @return [void] def route(controller, action, **args) klass = Object.const_get(klass_for(controller)).new klass.send(action, args) end # Fetch the class for the controller by name. # # @param controller [Symbol] # @raise [Vedeu::MissingRequired] When the given controller name does not # have a class defined. # @return [String] def klass_for(controller) if registered?(controller) && klass_defined?(controller) storage[controller][:klass] else fail Vedeu::MissingRequired, "Cannot route to #{controller} as no class defined." end end # Returns a boolean indicating whether the given controller name has a class # defined. # # @param controller [Symbol] # @return [Boolean] def klass_defined?(controller) present?(storage[controller][:klass]) end # Returns all the stored controllers and their respective actions. # # @return [Hash Hash String|Array>>] def storage @storage ||= in_memory end # Returns an empty collection ready for the storing of client application # controllers and actions. # # @return [Hash] def in_memory {} end end # Router end # Vedeu