|
NameGantry::Docs::FAQ - Frequently asked questions and answers about gantryIntroThis document is like a FAQ, except no one asked us these questions. We made the list to collect our knowledge in one place before we forgot it.The questions are:
InstallHow do I install Gantry?Method 1 (preferred): install via CPAN> perl -MCPAN -e shell cpan> install Gantry Method 2: Download the source (http://www.usegantry.org), extract it, change to that directory and run the following commands: > perl Build.PL > ./Build test > ./Build install Method 3: Check out Gantry from version control and then install > mkdir gantry > cd gantry > svn checkout http://gantry.googlecode.com/svn/trunk/ gantry > perl Build.PL > ./Build test > ./Build install Note that there are prerequisites. Further note that during testing some tests are skipped with warnings if you don't have suggested prerequisites. Installing the modules mentioned there is helpful. How do I install Gantry on Shared Hosting?Download the source, extract it, change to that directory and run the following commands:[ Note on Installing Dependancies: If your hosting provider will not install the module Dependancies you can just install them from source. You probably will not have access to install into the system perl directories. ] > perl Build.PL > ./Build test > ./Build install --install_base=<path to your local perl modules> CodingWhat is the smallest app I could write with Gantry?To see small Gantry apps consult Gantry::Docs::QuickStart and/or Gantry::Docs::Tutorial.How do I turn off templating to dump raw text?You can choose the formatting of your choice as long as your choice is Template Toolkit or no formatting. To choose the latter, in the use statement that initially loads Gantry (or more likely an app which uses it) specify -TemplateEngine=Default:use Gantry qw{ -TemplateEngine=Default } Alternatively, you can turn off formatting for one page request in the relavent handler: $self->template_disable( 1 ); Even after you turn automated TT off, you can still use it: $self->stash->view->template( 'your_temp_template.tt' ); my $partial_output = $self->do_process() || ''; I turned off templating must I hand write all HTML?Use the "Gantry::Utils::HTML" module to help you. This will often result in cleaner code with fewer tag problems. See its docs for details of the helper methods it provides.How do I use gantry's AutoCRUD?Once you have a database and a supported model for it, you can use Gantry's AutoCRUD. First,use Gantry::Plugins::AutoCRUD; This is more a mixin than a plugin. It exports do_add, do_edit, do_delete, and form_name into your module. The form_name method merely returns the text 'form.tt' which is the name of the default template for add/edit forms. If you want a different template, don't import form_name, instead implement your own form_name method. For the exported AutoCRUD methods to work you must implement three methods:
See the docs in Gantry::Plugins::AutoCRUD for additional optional methods. The other methods give you control over things like where users are taken when they cancel a request. If DBIx::Class is your object relational mapper (ORM), you need to implement get_orm_helper and have it return 'Gantry::Plugins::AutoCRUDHelper::DBIxClass'. If your ORM does not conform to the either the Class::DBI API or the to DBIx::Class API, you need to read the AutoCRUDHelpers section of the docs in Gantry::Plugins::AutoCRUD and provide your on helper module. What about retrieval?Your model should provide convenient retrieval methods. If you use DBIx::Class, you can inherit from Gantry::Utils::DBIxClass instead of from DBIx::Class to gain a couple of useful retrieval methods.Gantry's Gantry::Utils::CDBI inherits from CDBI::Sweet, so it responds to all the standard Class::DBI methods (with the Sweet additions). Both Gantry::Utils::DBIxClass and Gantry::Utils::CDBI provide get_listing which is suitable for most main listings. What if AutoCRUD won't work for me?Gantry::Plugins::AutoCRUD is somewhat rigid, but not as rigid as the above example makes it seem. For instance, suppose the above won't work because you need to specify a creation time for every add. AutoCRUD provides hooks.These are the hooks:
You may implement as many of these methods as you like in your controller. Any that are not implemented are simply not called. What if AutoCRUD really won't work for me?While the answer to the last question shows a certain amount of flexibility in the AutoCRUD scheme, sometimes it just isn't enough. If you want control, but don't want to worry with the basics of displaying the form, validating results, etc. Gantry::Plugins::CRUD is for you.To have a concrete example, suppose my controller posts comments on a blog entry, but only if the user is logged in. Unlike its AutoCRUD counterpart, Gantry::Plugins::CRUD does not export anything. Instead it is an object oriented helper. Here's how it works. First, use it: use Gantry::Plugins::CRUD; Then make an instance of it, being explicit about what it should do when: my $comment_crud = Gantry::Plugins::CRUD->new( add_action => \&add_comment, edit_action => \&edit_comment, delete_action => \&delete_comment, form => \&my_form, template => 'comment_form.tt', text_descr => 'comment', ); There are other keys you may use -- see the perldoc for Gantry::Plugins::CRUD for details. We'll look at the actions in some detail below. First, let's examine the other hash keys here. The form method must return a single value (usually a hash reference), which will go to the template that shows the form on the screen. The text_descr is used when asking the user to confirm a deletion. All that remains is to implement your own do_ methods to catch the CRUD requests for your controller. do_add { my ( $self, $blog_id ) = @_; unless ( $self->is_logged_in ) { die 'You must log in to post a comment' } $comment_crud->add( $self, { blog_id = $blog_id } ); } If the security check passes, the CRUD plugin's add method will take care of showing the comment form and validating the data on it. Once it is satisfied that the comment is valid, it will call add_comment (or whatever you registered as the add_action when you called the constructor). Here's an example: sub add_comment { my ( $self, $params, $data ) = @_; $params->{ blog_id } = $data->{ blog_id }; $params->{ user_id } = $self->user_id; $params->{ created } = 'now'; $params->{ body } = $self->sanitize_body( $params->{ body } ); my $new_row = Model::comments->create( $params ); $new_row->dbi_commit; $self->send_spam( $data->{ blog_id }, $new_row ); } You are completely responsible for updating the database in the add_action. A good model helps with this. The other actions work similarly. Note that there is no need to be completely honest with the names. It would a good use of Gantry::Plugins::CRUD to implement do_delete so that it marked rows as invisible rather than deleting them. That wouldn't be possible with AutoCRUD. As a final note, it is not necessary to define all the options for a Gantry::Plugins::CRUD object. It is fine to have only delete_action and the keys it needs. You may also have different objects for add, edit, and/or delete. This gives an easy way for add and edit to use different forms, for example. Can I use AutoCRUD and/or CRUD if I wrote my own models?This is really two questions. First, 'Can I use AutoCRUD with hand written models?' The answer is: Yes, so long as one of the following is true of your ORM. (1) it responds to dbi_commit, create and retrieve calls, the objects returned by retrieve respond to delete, and -- when your form is used for editing -- it expects a row object returned by your retrieve. (2) you implement a helper similar to Gantry::Plugins::AutoCRUDHelper::DBIxClass.Second, 'Can I use CRUD if I wrote my own models?' The answer is: Yes. For CRUD above restrictions don't apply since it works even if there is no model. How do I control error page appearance?When something in Gantry dies, the main handler traps the error and calls custom_error on the site object to generate the error page. Simply implement your own custom_error to change how the error output appears to your users. Note that it is often useful to change from a developer-friendly version to a user-friendly version as you move to production.The custom_error method is invoked on the site object. It receives an array of error output lines. How can I let my users pick dates easily?Date entry is controlled by form.tt. To make it work you need to do four things, the first two of them in them in your form method:
See Bigtop::Docs::Tutorial for how to make these steps happen from bigtop files. How can I use DBIx::Class with Gantry?There are several things you need to do to use DBIx::Class effectively with Gantry:
Bigtop can generate all of this for you. How can I use captchas to cut down spam on my site?Gantry has a utility which implements captchas. It even has a feature for disabled users. The user sees an image or its alt tag, then picks a description of it from a pull down menu. During form submission, the selected description is compared with encrypted text originally delivered with the form.To learn to use Gantry's captchas, see Gantry::Util::Captcha. How can I use Gantry's native models?Perhaps a better answer a question: 'Why would you want to?' If you have a good answer for that, the short answer to the original question is: use Bigtop. Better yet, use the tentmaker and select Model Gantry on the 'Backends' tab. Gantry's models require a lot of code. They were designed to be generated.DeploymentHow do I deploy a gantry app under mod_perl?There are three steps to placing most gantry apps under mod_perl.
How do I deploy a gantry app under CGI?Create an executable file in a cgi-bin directory like this one:#!/usr/bin/perl use strict; use App::Base::Module qw{ -Engine=CGI -TemplateEngine=TT }; my $cgi = Gantry::Engine::CGI->new( { locations => { '/' => 'App::Base::Module', '/sub' => 'App::Base::Module::Sub', '/sub2' => 'App::Base::Module::SubOther', '/sub/system' => 'App::Base::Module::Sub::System', } config { dbconn => 'dbi:Pg:dbname=mydb', dbuser => 'unknown', dbpass => 'none_of_your_business', root => '/home/you/templates:/home/gantry/root', } } ); $cgi->dispatch(); Adjust the config parameters to fit your app. Use as many locations as you like. How do I deploy a gantry app under FastCGI?FastCGI requires only a couple of slight changes to the above CGI script.Wrap the dispatch statement like this: use FCGI; my $request = FCGI::Request(); while ( $request->Accept() >= 0 ) { $cgi->dispatch(); } What is Gantry::Conf?Gantry::Conf provides a complete configuration scheme for both web and traditional programs. It allows you to share configuration between your web app and its cron scripts. It lets you run multiple instances of the same app in the same apache instance with separate configurations. It also lets you share configuration between apps even if they run on different servers (by allowing for http or https access to a single conf file).See Gantry::Conf::Tutorial for how to set up your conf files among other details. How should I configure an app?You should should use Gantry::Conf to configure your apps. On each system where you work, be it dev, qual, or prod, you should have a single directory where all the conf files live. We usually call it /etc/gantry.d, and I'll refer to it by that name below, but you could choose any directory that makes sense to you.Once you create /etc/gantry.d to hold the conf files or symbolic links to them, put this single line in your master conf file: include /etc/gantry.d/*.conf We call our single master conf file /etc/gantry.conf. Pick a file name that makes sense to you, use that name consistently across your systems. Finally, place one conf file for each app in the /etc/gantry.d directory. Alternatively, especially on dev systems, place a symbolic link in /etc/gantry.d which refers to the Gantry::Conf file bigtop regenerates for your application. Bigtop makes a conf file (if you request one) in the docs subdirectory of the build directory. To manually build a Gantry::Conf file, use a text editor to make something likes this: <instance YourAppName> dbconn dbi:Pg:dbname=yourdb dbuser somebody </instance> The format must be intelligible to "Conf::General" unless you tell Gantry::Conf to do something different. See Gantry::Conf for other ways to supply conf information. How you inform Gantry of your instance name varies by deployment approach. See the next three questions. Many apps need to be configured in different ways for different uses. For example, an app might need to contact one database server during development, but contact a different one in production. You might even have two instances of the same app presented to two different groups of production users. Gantry::Conf handles this with instances. You could just add another instance to the Gantry::Conf file for your app. But, you could also use Bigtop to help you. In Bigtop's app section, you may have as many config blocks as you like. You want one with no name, list it first. This will have the common conf information that all the instances will share. Then make additional config blocks with names to hold the variations: config { dbuser standard_user => no_accessor; template_wrapper site_wrapper.tt => no_accessor; people_per_page 25; } config dev { dbconn dbi:SQLite:dbname=app.db => no_accessor; people_per_page 4; } config prod { dbconn dbi:Pg:dbname=appdb;host=proddb.example.com => no_accessor; } This will result in a single Gantry::Conf file with multiple instances. Each instance will have all the conf variables from the base config block (the one with no name) and the ones from the named conf block. If both blocks have the same variable, the value from the named block overrides the one from the base block. There will be an instance for the base block, which will be named for the app. The other instance names will have the base instance name as a prefix with _name as a suffix. If the app with the above configs were called "HeavyLifter", the instances would be "heavylifter", "heavylifter_dev", and "heavylifter_prod". There are many other ways to use "Gantry::Conf", see its POD or read "Gantry::Conf::Tutorial" for more information. In each deployment, specify the proper instance in the appropriate manner as described in next three questions. How do I use Gantry::Conf under mod_perl?To make Gantry::Conf work, you must tell it which instance you need to configure. In mod_perl do this by setting this variable at the root location of your applications:PerlSetVar GantryConfInstance your_instance_name If you are not using the default /etc/gantry.conf for Gantry::Conf's configuration, set one additional variable: PerlSetVar GantryConfFile /full/path/to/your/conf.file How do I use Gantry::Conf under CGI/FastCGI?To make Gantry::Conf work, you must tell it which instance you need to configure. In CGI and FastCGI do this by setting this key in the config hash passed to the Gantry::Engine::CGI constructor:GantryConfInstance => 'your_instance_name' If you are not using the default /etc/gantry.conf for Gantry::Conf's configuration, set one additional variable: GantryConfFile => '/full/path/to/your/conf.file' How do I use Gantry::Conf outside of web servers?Suppose you have a cron job or script. To pull Gantry::Conf info for an instance into it, do something like this:use Gantry::Conf; my $instance = 'instance_name'; # could be a command line arg my $conf = Gantry::Conf->retrieve( { instance => $instance, config_file => '/etc/mygantry.conf', } ); This delivers a hash reference of conf information. If your master conf file is the default, /etc/gantry.conf, you may omit the "config_file" key. AppearanceWhere does Gantry look for style sheets, templates, etc.?The answer depends somewhat on how you deploy the application. Under CGI it looks in the config section of the hash you passed to Gantry::Engine::CGI->new. Under mod_perl it looks for PerlSetVar statements.In both cases the names it looks for are the same. Here are the ones Gantry.pm understands (these are highly integrated into the standard templates):
AuthenticationWhat tables do I need in my database for authentication?Gantry uses four tables for its authentication system. You can either put these into your app's database, or store them in another database. This allows you to share auth between multiple apps.The schema for the tables is in the SCHEMA FOR AUTH TABLES section of Gantry::Control#SCHEMA%20FOR%20AUTH%20TABLES. How do I add authentication to my app?Gantry provides integrated support for Apache's basic authentication. First, you need to have a database for authentication or put the auth tables into your app's database (see the previous question).Then, you need to add the following Apache directives to the base location for your app (or to the location at which auth should begin): <Location /myloc> AuthType Basic AuthName "Your Auth Realm Name" PerlSetVar auth_dbconn "dbi:Pg:dbname=your_auth_db" PerlSetVar auth_dbuser apache PerlSetVar auth_dbpass super_secret PerlAuthenHandler Gantry::Control::C::Access PerlAuthenHandler Gantry::Control::C::AuthenRegular PerlAuthzHandler Gantry::Control::C::AuthzRegular </Location> You need to set auth_dbconn, auth_dbuser, and auth_dbpass even if your auth tables are in your app's database. Finally, add directives to the proper locations: require group NAME require valid-user If you want to limit access by IP, set this perl var for the location: PerlSetVar auth_allow_ips "172.168.2.41,172.168.2.182' Note: if you are doing anything important, you should run it through ssh to keep the sniffers from seeing your passwords. How do I add gantry authentication to my non-gantry app?You don't need a gantry app to use gantry's auth modules. Simply follow the instructions in the answer to the previous question.How do I add gantry authentication to my static page location?You don't even need an app to use gantry's auth modules. Just do the same thing you would do if you had an app.How can I share my authentication database across multiple apps?Two or more apps can share one auth database by setting their auth_dbconn to the same connection string. This does require a bit of coordination in the auth_groups and auth_group_members tables.ScriptsHow can my cron (and other) scripts use an app's models?If you use DBIx::Class, do its normal thing:my $schema = Your::Schema->connect( 'dbi:Pg:dbname=yourdb;host=127.0.0.1', 'user', 'pass' ); But note that Bigtop generates the schema as Model.pm, even though it is not a model and no models inherit from it. If you use any ORM which uses the DBConn scheme (see Gantry::Docs::DBConn), your script should use the provided helper: use Gantry::Utils::Helper::Script; Gantry::Utils::Helper::Script->set_conn_info( { dbconn => 'dbi:Pg:dbname=yourdb;host=127.0.0.1', dbuser => 'auser', dbpass => 'secret', } ) Change the methods as needed (to reflect your database names, user, and password or to allow the main package to fill in the values from command line args or config file info). This works for all models which inherit from Gantry::Utils::CDBI. If any of your models inherit from Gantry::Utils::AuthCDBI, then you must include auth_conn_info. Gantry::Utils::Helper::Script->auth_conn_info( { auth_dbconn => 'dbi:Pg:dbname=yourauthdb;host=127.0.0.1', auth_dbuser => 'auser', auth_dbpass => 'super_secret', } ); Note that some models which inherit from Gantry::Utils::CDBI might have foreign keys pointing to other models which inherit from Gantry::Utils::AuthCDBI. In that case, even though you don't directly see the need for auth, you do in fact need it. SummaryIf you have other questions, send them in to the gantry mailing list -- details on joining can be found on http://usegantry.org. Maybe some day this will be a genuine FAQ.AuthorPhil Crow <philcrow2000@yahoo.com>Tim Keefer <tkeefer@gmail.com> Copyright and LicenseCopyright (c) 2006, Phil Crow.This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.
Visit the GSP FreeBSD Man Page Interface. |