Bigtop

 view release on metacpan or  search on metacpan

lib/Bigtop/Docs/Cookbook.pod  view on Meta::CPAN

the GEN module.

Note that both the GEN module and Gantry::Plugins::AutoCRUD are mixins (they
export methods).  If you don't want their standard methods, don't include
them in the import lists.  But, if you don't want the ones from
Gantry::Plugins::AutoCRUD, you probably want real CRUD (see below).

=head2 How do I use Gantry's CRUD?

Gantry's AutoCRUD has quite a bit of flexibility (e.g. it has pre and post
callbacks for add, edit, and delete), but sometimes it isn't enough.
Even when it is enough, some people prefer explicit schemes to implicit
ones.  CRUD is more explicit.  To use it do this:

    controller NotSoSimple is CRUD {
        text_description `Not So Simple Item`;
        method my_crud_form is CRUD_form {
            form_name simple
            fields    name, address;
            extra_keys
                legend => `$self->path_info =~ /edit/i ? 'Edit' : 'Add'`;

lib/Bigtop/Docs/Cookbook.pod  view on Meta::CPAN

    # $self->do_add( )
    #-------------------------------------------------
    sub do_add {
        my $self = shift;

        $my_crud->add( $self, { data => \@_ } );
    }

(do_edit and do_delete are similar.)

Finally, it provides the callbacks.  For example:

    #-------------------------------------------------
    # $self->my_crud_add( $id )
    #-------------------------------------------------
    sub my_crud_add {
        my ( $self, $params, $data ) = @_;

        # make a new row in the $YOUR_TABLE table using data from $params
        # remember to commit
    }

It also makes my_crud_edit, my_crud_delete, and my_crud_redirect.
Note that you don't get actual code for updating your database, just
comments telling you what normal people do.  Of course, abnormality is
one of the main reasons for using CRUD instead of AutoCRUD, so take
the comments with a grain of salt.

Note that if you have more than one method of type CRUD_form, the bigtop
backend will make multiple crud objects (each named for its form)
and the callbacks for those objects.  But it will also make multiple
do_add, do_edit, and do_delete methods.  They will make their calls through
the proper crud object, but their names will be duplicated.  In that
case, you are on your own to change them to reasonable (i.e. non-clashing)
names.

=head1 Using Gantry's ORM Help

=head2 What does the GantryDBIxClass Model backend make?

The Model GantryDBIxClass backend makes a pair of modules for each table.

lib/Bigtop/Docs/Modules.pod  view on Meta::CPAN

     my $sql_output   = join '', @{ $sql };

The lookup subtree of the application subtree provides easier access to
the data in the tree (though it doesn't have all the connectors the AST
has for parsing use, in particular it uses hashes exclusively, so it never
intentionally preserves order).

I let Bigtop::Parser's walk_postorder do the visiting of tree nodes
for me.  It will call 'output_sql_lite' on each of them.  I implement that
on the packages my SQL generator cares about below.  I pass the lookup
hash to walk_postorder so it will be available to the callbacks.

Note that the name of the walk_postorder action needs to be unique among
all Bigtop::Backend::* modules.  This prevents subroutine redefinitions
(and their warnings) when multiple SQL backends are in use.  It also
makes tentmaker run more quietly in all cases.  Choose names with some
tag relating to your backend to avoid namespace collisions.

The output of walk_postorder is always an array reference.  I join it
together and store it in $sql_output.

lib/Bigtop/Docs/Modules.pod  view on Meta::CPAN

        $template_is_setup = 1;
    }

The parser calls this (if the package can respond to it) prior to
calling gen_SQL.  If the user has supplied an alernate template, it
is passed to setup_template.

To avoid bad template binding, $template_is_setup keeps track of whether
we've been here before.

Inline's bind method creates subs in the current name space for callbacks
to use.  Note that if $template_text is a file name, that file will be
bound correctly.

I've tried to abstract out this code so all backends can share it, but
the nature of Inline bindings makes that difficult, so I gave up.

=head3 Real work

All that remains is the real work.  We need to implement output_sql in
about half a dozen packages.

lib/Bigtop/Docs/Modules.pod  view on Meta::CPAN

             keyword      => $self->get_create_keyword(),
             child_output => $child_out_str,
             name         => $self->get_name(),
         }
     );
  
     return [ $output ];
 }


As all callbacks do, this one receives the current tree node as its
invocant and the output of its children as parameters.  (It also
receives the data passed to walk_postorder, but this method doesn't need it.)

The child output comes from the walk_postorder method of this package.
It is always an array reference.  In this case, that array has one or more
subarrays.  Each of those has two elements: type and text.  The types
are: table_body and insert_statements.  The table_body elements must
go inside the body of the CREATE TABLE statement.  The insert_statements
must be placed after the CREATE TABLE statement.  There is one of those
for each data statement in the table block of the Bigtop file.

lib/Bigtop/Parser.pm  view on Meta::CPAN

        Bigtop::write_file( $build_dir, $something_string );
    }

This walks the tree from the root.  The walking is postorder meaning that
all children are visited before the current node.  Each walk_postorder
returns an array reference (which is why we have to join the result
in the above skeleton).  After the children have been visited, the
callback (C<output_something> in the example) is called with their output
array reference.  You can also pass an additional scalar (which is usually
a hash reference) to walk_postorder.  It will be passed along to all
the child walk_postorders and to the callbacks.

With this module walking the tree, all you must do is provide the appropriate
callbacks.  Put one at each level of the tree that interests you.

For example, if you are generating SQL, you need to put callbacks in
at least the following packages:

    table_block
    table_element_block
    field_statement

This does require some knowledge of the tree.  Please consult bigtop.grammar,
in the lib/Bigtop subdirectory of Bigtop's build directory,
for the possible packages (or grep for package on this file).
There are also several chapters of the Gantry book devoted to explaining
how to use the AST to build backends.

The callbacks are called as methods on the current tree node.  They receive
the output array reference from their children and the data scalar that
was passed to walk_postorder (if one was passed in the top level call).
So, a typical callback method might look like this:

    sub output_something {
        my $self         = shift;
        my $child_output = shift;
        my $data         = shift;
        ...
        return [ $output ];

lib/Bigtop/Parser.pm  view on Meta::CPAN

    }

The easiest way to know what is available is to dump the lookup hash.
But the pattern is basically this.  At the top level there are fixed keywords
for the app level block types: tables, sequences, controllers.  The next
level is the name of a block.  Under that, there is a fixed keyword for
each subblock type, etc.

=back

=head2 METHODS for use in walk_postorder callbacks

=over 4

=item dumpme

Use this method instead of directly calling Data::Dumper::Dump.

While you could dump $self, that's rather messy.  The problem is the parent
nodes.  Their presence means a simple dump will always show the whole app
AST.  This method carefully removes the parent, dumps the node, and restores



( run in 2.663 seconds using v1.01-cache-2.11-cpan-9b1e4054eb1 )