This document is a humble attempt to explain the internal workings of Ramaze and how the different parts fit into the big picture. It does not try to describe every little detail, as you will be better off reading the actual source instead. But you will at least get an idea of where to look. ### Ramaze Ramaze is a web framework and therefor tries to make it simple to deploy your own applications on top of it. Let's outline the realms that Ramaze works in as to show what the current limitations and features are. #### The Ramaze module Ramaze is also the main module or so-called namespace that the framework lives in. It has Tasks on require * Inform * LogHub.new(Informer) * Global * GlobalStruct.new Tasks on startup * Global.startup * passed options to Ramaze.start * CLI options from bin/ramaze (treat as passed.merge) * Global options set before startup (fake Global?) * Controller.startup * mapping of all subclassed Controller * validation of mapping * validation of template_root * Adapter.startup * interpret Global.adapter * add every created adapter to Global.adapters * SourceReload.startup * start with Global.reload_interval * assign Global.sourcereload Tasks on shutdown * Adapter.shutdown (iterates Global.adapters) * Inform.shutdown (iterates all in LogHub) #### Global configuration Any serious application or framework needs to be configured. Yes, I wished there was a silver bullet to serve all your needs as well, but at the current stage of programming development there is no such thing. So, since we need to configure, we should make it as simple and painless as possible, and, thanks to Ruby, it is actually quite enjoyable to do that. You can find a very detailed description about Global in the section about Configuration, for now just the basics. The basis of Ramaze::Global, the instance that is holding most part of your configuration or at least links to the actual places, is the Ramaze::GlobalStruct (ramaze/global.rb), which is a subclass of OpenStruct. If you are not yet familiar with OpenStruct, I very much recommend to read its documentation and play around a bit, it is basically just a wrapper around a normal Hash where you can access the keys instead of ostruct[:foo] with ostruct.foo. It simply defines a new accessors on assignment by catching things in method_missing. I won't go into more details here, I hope you got the principle. Now, based on this technique, GlobalStruct adds things like defaults and a couple of convenience methods like they are common in Ruby, giving you more power by tapping to the internal Hash of the GlobalStruct and adding update/setup methods so you can assign many key/value pairs at once. The RDocs will give you a very good overview of what is available and how one is supposed to work with it. Now back to the big picture. Ramaze accesses Global all over the place, there have been made several choices as to why using something like Global is considered beneficial against choosing for example global variables, which would be considered as a fatal choice by any respected Rubyist anyway. Now to something more subtle, which has to do with Global. I speak about traits, which is a very different concept in most of its implementations, but it is something that basically fits this name. It is configuration of single Objects and whole ancestries. You can give an object a trait, and most likely will use it along the lines of something like MyController.trait(:map => '/'), which would be picked up on startup and used to create Global.mapping - where we are at configuration again. Choosing this style of configuration complementary to a central place to put all your configuration was made very early in the development of Ramaze, and the basic code of how traits are implemented and used has proven very efficient both in understanding and using them. There is a basic distinction when to use Global and when to use traits and when to generate or assume one based on the other. If something affects your whole application and is either used directly in the Ramaze module or throughout the framework it is considered to be put into Global to gain benefits of better documentation and accessibility. On the other hand - if something is used in a configuring manner by a class that is instantiated often (like Controller is for example), or a module that cannot hold instance variables in a nice manner and is also not a constant - then it is configured using traits. Ramaze Global Adapter Dispatcher Controller Action Session Helper Tool #### The Web The so called web consists of a plethora of data, most of it is browsable through a web browser that just about every toaster has installed these days. The browser is the target of a web author, trying to utilize common standards like HTML and CSS which are means for data and layout to be combined, giving the browser a way to display the data. Ramaze works on the URI-scale web, meaning that addresses like http://someserver.com/blog/article/1 have a unique representation on your server. If we stay with this example, we see already everything Ramaze needs to see to serve a page based on your instructions. We assume that blog/article is a Controller named ArticleController in the blog application.