<?xml version="1.0"?>
<rss version="2.0">
  <channel><title>Internals</title><link>http://bill.welliver.org//space/pike/Fins/Internals</link><description>Getting started with Fins and&#xD;
The inner workings of a Fins Application.&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Prerequisites&lt;p class="paragraph"/&gt;&lt;/h3&gt;
Fins runs on Pike 7.8 or higher. Bonjour ready systems &#xD;
(such as MacOS X) will get you automatic announcement of your Fins apps. &#xD;
If you want to use the optional XSLT templating system, you'll need to install libxml, &#xD;
libxslt and the Public.Parser.XML2 module.&lt;p class="paragraph"/&gt;
There are some prerequisite modules that you'll need; to avoid having to install them, you should check out the starter bundle at &lt;a href="/space/pike/Fins/Windows"&gt;Windows&lt;/a&gt;.&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Creating a new application&lt;p class="paragraph"/&gt;&lt;/h3&gt;
To create a new web application, simply create the following file &#xD;
hierarchy, or use the &lt;i class="ital"&gt;fins&lt;/i&gt; tool to create one. You'll probably want to customize all of the files in it, &#xD;
based on your needs.&lt;p class="paragraph"/&gt;
&lt;div class="code"&gt;&lt;pre&gt;&lt;pre&gt;&#xD;
pike -x fins create MyNewApp&#xD;
&lt;/pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;
&#xD;
Once the app is created, you should edit the config file in &lt;i class="ital"&gt;MyNewApp/config/dev.cfg&lt;/i&gt;, to either define a model datasource or comment the entire "model" section out. If you don't do one of these, Fins will bail out because it won't be able to load the model.&lt;p class="paragraph"/&gt;
After you have customized the configuration file, you can start up the application by running the following command (the &lt;i class="ital"&gt;MyNewApp&lt;/i&gt; directory should be in your current directory):&lt;p class="paragraph"/&gt;
&lt;div class="code"&gt;&lt;pre&gt;&lt;pre&gt;&#xD;
pike -x fins start MyNewApp&#xD;
&lt;/pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;
&#xD;
&lt;i class="ital"&gt;or&lt;/i&gt;&lt;p class="paragraph"/&gt;
&lt;div class="code"&gt;&lt;pre&gt;&lt;pre&gt;&#xD;
cd MyNewApp&#xD;
bin/start.sh&#xD;
&lt;/pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Absolute Bare Minimum&lt;p class="paragraph"/&gt;&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre&gt;&lt;pre&gt;&#xD;
APPDIR/&#xD;
APPDIR/config&#xD;
APPDIR/config/dev.cfg&#xD;
APPDIR/classes/application.pike&#xD;
APPDIR/classes/controller.pike &#xD;
&lt;/pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;
&#xD;
(technically, the last file is optional, however the app won't really do much without it).&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Optional bare-minimum components&lt;p class="paragraph"/&gt;&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre&gt;&lt;pre&gt;&#xD;
APPDIR/classes/view.pike&#xD;
APPDIR/classes/model.pike&#xD;
APPDIR/templates/*&#xD;
APPDIR/modules/*&#xD;
&lt;/pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;
&#xD;
A Fins application is stored with an application directory dedicated &#xD;
specifically to that application. Typically the application directory &#xD;
(which will call APPDIR) is named for the application, though this is not &#xD;
a requirement.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;APPDIR/&lt;/b&gt;&lt;p class="paragraph"/&gt;
This is the root of the application, and the full path to this directory &#xD;
is included as application-&gt;config-&gt;app_dir&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;APPDIR/config&lt;/b&gt;&lt;p class="paragraph"/&gt;
This directory holds any necessary configuration files; at a minimum, a &#xD;
fins application consists of a config file and an application class. The &#xD;
files are named configname.cfg, where configname is the string passed as &#xD;
the configuration name argument to fin_serve. If no configuration name is &#xD;
supplied, it is assumed to be "dev". The format of the configuration file &#xD;
is similar to windows style "ini" files, which is broken into sections, &#xD;
with one or more values in each section.&lt;p class="paragraph"/&gt;
Your application may use the configuration file to store its own data &#xD;
using the application-&gt;config object. Fins has a few settings that are &#xD;
required:&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;&amp;#91;model]&lt;/b&gt; &lt;- optional, not necessary if you do not have a model in your app.&lt;p class="paragraph"/&gt;
key-value pairs (if the model section is present, these values are &#xD;
mandatory):&lt;p class="paragraph"/&gt;
class: the name of the class that implements Fins.FinsModel and will load &#xD;
all of your custom datatypes. Normally, this is "model".&lt;p class="paragraph"/&gt;
datasource: the sql url of the database underlying your model.&lt;p class="paragraph"/&gt;
debug: if set to "1", all sql statements generated by the model will be &#xD;
written to stderr.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;&amp;#91;controller]&lt;/b&gt; &lt;- required&lt;p class="paragraph"/&gt;
key-value pairs (all mandatory):&lt;p class="paragraph"/&gt;
class: the name of a class that implements Fins.FinsController.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;&amp;#91;view]&lt;/b&gt; &lt;- optional, not necessary if you do not have a view in your app.&lt;p class="paragraph"/&gt;
key-value pairs (all mandatory):&lt;p class="paragraph"/&gt;
class: the name of a class that implements Fins.FinsView.&lt;p class="paragraph"/&gt;
reload: if set to "1", all first level templates will be checked for &#xD;
changes on each request, and reloaded if necessary. Currently this does &#xD;
not include files included using include directives.&lt;p class="paragraph"/&gt;
&#xD;
&lt;b class="bold"&gt;APPDIR/classes&lt;/b&gt;&lt;p class="paragraph"/&gt;
This directory should contain the pike classes you application requires, &#xD;
such as the application, model, view, and any controllers. Normally model &#xD;
object definitions would be stored in a module within the modules &#xD;
directory. This directory is placed in the Pike program path, so you can &#xD;
do things like (program)"myclass" and have the file myclass.pike compiled &#xD;
into a program.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;APPDIR/modules&lt;/b&gt;&lt;p class="paragraph"/&gt;
This directory can be used to store any application specific modules. A &#xD;
good example of classes and modules to place in this directory is model &#xD;
related object types.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;APPDIR/static&lt;/b&gt;&lt;p class="paragraph"/&gt;
Files contained within this directory are made automatically available on &#xD;
the path /static/. Additionally, a file "favicon.ico" placed in this &#xD;
directory will be automatically short-circuited from /favicon.ico. Note &#xD;
that content in this directory is not subject to any access restrictions, &#xD;
so sensitive content should be placed under the control of a secured &#xD;
controller. Also, directory listings are not generated from this &#xD;
directory; you must request a file directly.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;APPDIR/templates&lt;/b&gt;&lt;p class="paragraph"/&gt;
Templates used by the Fins.Template framework are stored within this &#xD;
directory by default (though custom templates can retrieve their source &#xD;
from any location, in theory).&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Application startup process&lt;p class="paragraph"/&gt;&lt;/h3&gt;
Note that Fins makes use of Pike's object orientation features, so that &#xD;
most application startup and operations behavior can be overridden by &#xD;
implimenting replacement classes. Examples include XMLRPCController and &#xD;
DocController. Every application inherits Fins.Application, and by &#xD;
default, basic application setup is performed so that only a few functions &#xD;
need to be provided.&#xD;
&lt;ol&gt;
&lt;li&gt;classes and modules are added to the program and module paths, respectively.&lt;/li&gt;
&lt;li&gt;the configuration file is parsed and loaded.&lt;/li&gt;
&lt;li&gt;the file classes/application.pike is compiled and instantiated. the configuration is passed to the constructor. see section 2, Fins.Application initialization.&lt;/li&gt;
&lt;li&gt;any listeners are started up by the respective servicing application (fin_serve, caudium module, etc).&lt;/li&gt;
&lt;/ol&gt;1 Fins.Application initialization&#xD;
&lt;ol&gt;
&lt;li&gt;application-&gt;config is set with the configuration file&lt;/li&gt;
&lt;li&gt;load_cache() is called, which instantiates a copy of the Fins.Cache&lt;/li&gt;
&lt;li&gt;load_model() is called, which instantiates the class specified in the model section of the config file (if it exists). See Fins.FinsModel initialization for details.&lt;/li&gt;
&lt;li&gt;load_view() is called, which instantiates the class specified in the model section of the config file (if it exists). See Fins.FinsView initialization for details.&lt;/li&gt;
&lt;li&gt;load_controller() is called, which instantiates the class specified in the controller section of the config file (if it exists). See Fins.FinsView initialization for details.&lt;/li&gt;
&lt;li&gt;start() is called.&lt;/li&gt;
&lt;/ol&gt;1 Fins.FinsModel initialization&lt;p class="paragraph"/&gt;
inherits Fins.FinsBase, which provides app, cache, view, config and model &#xD;
as local variables.&#xD;
&lt;ol&gt;
&lt;li&gt;constructor is called with the application object passed as an argument.&lt;/li&gt;
&lt;li&gt;load_model() is called within the local class.&lt;/li&gt;
&lt;li&gt;an instance of Sql.Sql is created using the SQL datasource url provided in the model section of the config file.&lt;/li&gt;
&lt;li&gt;an instance of Fins.Model.DataModelContext is created&lt;/li&gt;
&lt;li&gt;the repository, cache, app and sql connection are populated in the DataModelContext object&lt;/li&gt;
&lt;li&gt;the DMC is initialize()ed, which configures the model rdbms abstraction code for the particular database personality being used.&lt;/li&gt;
&lt;li&gt;the method register_types() is called, which is something you should populate with repository-&gt;add_object_type() calls, unless you're using auto-model registration, which is described more fully at &lt;a href="/space/pike/Fins/Developer/Model"&gt;Model&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;1 Fins.FinsView initialization&lt;p class="paragraph"/&gt;
inherits Fins.FinsBase, which provides app, cache, view, config and model &#xD;
as local variables.&lt;p class="paragraph"/&gt;
default_template, default_data and default_context are all pre-populated &#xD;
with classes from Fins.Template, making Fins.Template.Simple the default &#xD;
template type.&#xD;
&lt;ol&gt;
&lt;li&gt;constructor is called with the application object passed as an argument.&lt;/li&gt;
&lt;li&gt;load_macros() is called, which registers all functions that start with simple_macro_ as simple template macros.&lt;/li&gt;
&lt;/ol&gt;1 Fins.FinsController initialization&lt;p class="paragraph"/&gt;
inherits Fins.FinsBase, which provides app, cache, view, config and model &#xD;
as local variables.&lt;p class="paragraph"/&gt;
you should add approppriate event handlers and sub controllers as &#xD;
necessary. normally you would place the instantiation code for any &#xD;
sub-controllers within start(), and pass the app object to the &#xD;
constructor. the sub-controllers will be "mounted" in the virtual &#xD;
filesystem at a subdirectory corresponding to the name of the variable &#xD;
that they are assigned to within the controller.&#xD;
&lt;ol&gt;
&lt;li&gt;constructor is called with the application application object as an argument.&lt;/li&gt;
&lt;li&gt;start() is called in the controller.&lt;/li&gt;
&lt;/ol&gt;1 How do my requests get directed?&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;Event Methods&lt;/b&gt;&lt;p class="paragraph"/&gt;
Any public functions present in your controller will be available as &#xD;
paths on your url; if no path is provided, the index method will be run. The base FinsController class expects event methods that take a Fins.Request object, a Fins.Response object and an argument of type "mixed ..." which will contain any arguments.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;Event Method Example:&lt;/b&gt;&lt;p class="paragraph"/&gt;
If you have a method called "boo" in your main controller, it will be &#xD;
available as "/boo". Any additional path past that will be sent as &#xD;
arguments to the method.&lt;p class="paragraph"/&gt;
Note that your index function can't receive "arguments", as they could &#xD;
potentially mask other methods.&lt;p class="paragraph"/&gt;
&#xD;
&lt;b class="bold"&gt;Sub-controllers&lt;/b&gt;&lt;p class="paragraph"/&gt;
If you have a controller class present within &#xD;
the main controller, it will also be available as a subfolder on your &#xD;
application url.&lt;p class="paragraph"/&gt;
&lt;b class="bold"&gt;Sub-controller Example:&lt;/b&gt;&lt;p class="paragraph"/&gt;
For example, if you have a controller class called &#xD;
"gazonk" in your main controller, the sub-controller will be available as &#xD;
"/gazonk/". note that if you just choose "/gazonk", you'll automatically &#xD;
be redirected so that you're at the "index" level of that controller.&lt;p class="paragraph"/&gt;
Also, your controller should instantiate any sub-controllers from the start() function within the parent controller. Always pass the app object to the constructor of your controllers.&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Starting a Fins application&lt;p class="paragraph"/&gt;&lt;/h3&gt;
Right now, the only way to run a Fins application is with the built in &#xD;
webserver (not that it's that bad). To start up your application, make sure that &lt;i class="ital"&gt;Fins/lib&lt;/i&gt; is in your pike module path and then run the fins start program:&lt;p class="paragraph"/&gt;
&lt;div class="code"&gt;&lt;pre&gt;&lt;pre&gt;&#xD;
pike -x fins start &amp;#91;-p &amp;#91;port]|--hilfe] &amp;#91;appname &amp;#91;config]] &#xD;
&lt;/pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;
&#xD;
where port is the port number your Fins application should run on, which &#xD;
defaults to port 8080. appname is the name of the app you'd like to run. &#xD;
it defaults to "default". config is the name of a configuration you'd &#xD;
like to use, which is loaded from appname/config/config.cfg. this value &#xD;
defaults to dev, which loads config/dev.cfg. if you have a Bonjour &#xD;
subsystem and Pike 7.7, you'll get automatic bookmarks in your Bonjour &#xD;
aware applications (such as Safari).&lt;p class="paragraph"/&gt;
&lt;h3 class="heading-1"&gt;Interactive Fins&lt;p class="paragraph"/&gt;&lt;/h3&gt;
fin_serve also supports an interactive "hilfe" mode. This is just like &#xD;
regular hilfe, only your application is loaded and initialized, so that &#xD;
you can call functions within your application, such as the model, &#xD;
interactively.&lt;p class="paragraph"/&gt;
you can access your application through the "application" constant.&#xD;
</description><generator>Fins 0.9.7</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs></channel>
</rss>
