package Bigtop::Backend::Model::GantryDBIxClass;
use strict; use warnings;
use Bigtop::Backend::Model;
use File::Spec;
use Inline;
use Bigtop;
#-----------------------------------------------------------------
# Register keywords in the grammar
#-----------------------------------------------------------------
BEGIN {
Bigtop::Parser->add_valid_keywords(
Bigtop::Keywords->get_docs_for(
'field',
'accessor',
'add_columns',
)
);
}
#-----------------------------------------------------------------
# The Default Template
#-----------------------------------------------------------------
our $template_is_setup = 0;
our $default_template_text = <<'EO_TT_blocks';
[% BLOCK stub_base_model %]
package [% app_name %]::Model;
use strict; use warnings;
use base 'DBIx::Class::Schema';
use [% app_name %]::GENModel;
sub get_db_options {
return { AutoCommit => 1 };
}
1;
=head1 NAME
[% app_name %]::Model - schema class for [% app_name +%]
=head1 SYNOPSIS
In your base module:
use [% app_name %]::Model;
sub schema_base_class { return '[% app_name %]::Model'; }
use Gantry::Plugins::DBIxClassConn qw( get_schema );
[%- FOREACH table_model IN table_models -%]
use [% app_name %]::Model::[% table_model %] qw( $[% table_model | upper %] );
[%- END -%]
=head1 DESCRIPTION
This module was generated by Bigtop. But, feel free to edit it. You
might even want to update these docs.
=over 4
=item get_db_options
The generated version sets AutoCommit to 1, this assumes that you will
do all transaction work via the DBIx::Class API.
=back
=head1 DEPENDENCIES
Gantry::Utils::DBIxClass
[% app_name %]::GENModel
=head1 AUTHOR
[% FOREACH author IN authors %]
[% author.0 %][% IF author.1 %], E<lt>[% author.1 %]E<gt>[% END %]
[% END %]
=head1 COPYRIGHT AND LICENSE
Copyright (C) [% year %] [% copyright_holder %]
[% IF license_text %]
[% ELSE %]
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.
[% END %]
=cut
[% END %]
[% BLOCK gen_base_model %]
package [% app_name %]::Model;
use strict; use warnings;
__PACKAGE__->load_classes( qw/
[% FOREACH table_model IN table_models %]
[% table_model %]
[% END %]
/ );
1;
=head1 NAME
[% app_name %]::GENModel - regenerating schema for [% app_name %]
=head1 SYNOPSIS
In your base schema:
use base 'DBIx::Class::Schema';
use [% app_name %]::GENModel;
=head1 DESCRIPTION
This module was generated by Bigtop (and IS subject to regeneration).
=head1 DEPENDENCIES
Gantry::Utils::DBIxClass
=head1 AUTHOR
[% FOREACH author IN authors %]
[% author.0 %][% IF author.1 %], E<lt>[% author.1 %]E<gt>[% END %]
[% END %]
=head1 COPYRIGHT AND LICENSE
Copyright (C) [% year %] [% copyright_holder %]
[% IF license_text %]
[% ELSE %]
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.
[% END %]
=cut
[% END %]
[% BLOCK stub_table_module %]
package [% package_name %];
use strict; use warnings;
use base '[% base_class || base_class_default %]', 'Exporter';
use [% gen_package_name %];
our $[% package_alias %] = '[% package_name %]';
our @EXPORT_OK = ( '$[% package_alias %]' );
1;
=head1 NAME
[% package_name %] - model for [% table_name %] table (stub part)
=head1 DESCRIPTION
This model inherits from its generated helper, which inherits from
[% base_class || base_class_default %]. It was generated by Bigtop, but is
NOT subject to regeneration.
=head1 METHODS (mixed in from [% gen_package_name %])
You may use all normal [% base_class || base_class_default %] methods and the
ones listed here:
=over 4
=item get_foreign_display_fields
=item get_foreign_tables
=item foreign_display
=item table_name
[% FOREACH option_field IN option_fields %]
=item [% option_field.name %]_display
[% END %]
=back
=cut
[% END %]
[% BLOCK gen_table_module %]
# NEVER EDIT this file. It was generated and will be overwritten without
# notice upon regeneration of this application. You have been warned.
package [% package_name %];
use strict; use warnings;
__PACKAGE__->load_components( qw/ [% load_components %] / );
__PACKAGE__->table( '[% real_table_name %]' );
__PACKAGE__->add_columns( qw/
[% FOREACH column IN regular_accessor_columns %]
[% column +%]
[% END %]
/ );
[% IF special_accessor_columns.size > 0 %]
__PACKAGE__->add_columns(
[% FOREACH column IN special_accessor_columns %]
[% column.name %] => { accessor => '[% column.accessor %]', },
[% END %]
);
[% END %]
[% IF add_columns.size > 0 %]
__PACKAGE__->add_columns(
[% FOREACH column IN add_columns %]
[% column.name %] => {
[% FOREACH pair IN column.pairs %]
[% pair.key %] => '[% pair.value %]',
[% END %]
},
[% END %]
);
[% END %]
[% IF primary_key.0.defined %]__PACKAGE__->set_primary_key( [ qw( [% FOREACH pk IN primary_key %][% pk %][% UNLESS loop.last %] [% END %]
[% END %] ) ] );
[% ELSIF primary_key %]__PACKAGE__->set_primary_key( '[% primary_key +%]' );[% END +%]
[% FOREACH uq_cons_name IN unique_name.keys.sort %]
__PACKAGE__->add_unique_constraint(
[% uq_cons_name %] => [ qw/[% FOREACH uq IN unique_name.${uq_cons_name} %][% uq %][% UNLESS loop.last %] [% END %][% END %]/ ]
);
[% END %]
[% FOREACH has_a IN has_a_list %]
__PACKAGE__->belongs_to( [% has_a.column %] => '[% base_package_name %]::[% has_a.table %]' );
[% END %]
__PACKAGE__->base_model( '[% app_name %]::Model' );
[% FOREACH has_many IN has_manys %]
__PACKAGE__->has_many( [% has_many.name %] => '[% app_name %]::Model::[% has_many.table %]'[% IF has_many.field.defined %], '[% has_many.field %]'[% END %] );
[% END %]
[% FOREACH has_many IN three_ways %]
__PACKAGE__->has_many(
[% has_many.join_name %] => '[% has_many.three_way_model %]',
'[% has_many.current_table %]'
);
__PACKAGE__->many_to_many(
[% has_many.foreign_name %] => '[% has_many.join_name %]',
'[% has_many.foreign_key %]'
);
[% END %]
[% IF foreign_display_columns %]sub get_foreign_display_fields {
return [ qw( [% foreign_display_columns %] ) ];
}
[% END %]
sub get_foreign_tables {
return qw(
[% FOREACH foreign_table IN foreign_tables %]
[% base_package_name %]::[% foreign_table +%]
[% END %]
);
}
[% IF foreign_display_columns %]sub foreign_display {
my $self = shift;
[% foreign_display_body %]
}
[% END %]
sub table_name {
return '[% table_name %]';
}
[%- IF option_fields.0 +%]
[% extra_methods = [] %]
my %select_map_for = (
[% FOREACH option_field IN option_fields %]
[% meth_name = option_field.name;
extra_methods.push( "${meth_name}_display" ) %]
[% option_field.name %] => {
[% FOREACH option IN option_field.options %]
[% option.db_value %] => '[% option.label %]',
[% END %]
},
[% END %]
);
[% FOREACH option_field IN option_fields %]
sub [% option_field.name %]_display {
my $self = shift;
my $[% option_field.name %] = defined $self->[% option_field.name %] ? $self->[% option_field.name %] : '';
return $select_map_for{ [% option_field.name %] }{ $[% option_field.name %] }
|| $[% option_field.name %];
}
[% END %]
[% END %]
1;
=head1 NAME
[% gen_package_name %] - model for [% table_name %] table (generated part)
=head1 DESCRIPTION
This model inherits from [% base_class || base_class_default %].
It was generated by Bigtop, and IS subject to regeneration.
=head1 METHODS
You may use all normal [% base_class || base_class_default %] methods and the
ones listed here:
=over 4
=item get_foreign_display_fields
=item get_foreign_tables
=item foreign_display
=item table_name
[% FOREACH extra_method IN extra_methods %]
=item [% extra_method +%]
[% END %]
=back
=cut
[% END %]
[% BLOCK gen_three_way_module %]
package [% stub_package %];
use strict; use warnings;
use base '[% model_base_class %]', 'Exporter';
use [% gen_package %];
our $[% package_alias %] = '[% stub_package %]';
our @EXPORT_OK = ( '$[% package_alias %]' );
1;
=head1 NAME
[% stub_package %] - model for [% table_name %] table (stub part)
=head1 DESCRIPTION
This model inherits from its generated helper, which inherits from
Gantry::Utils::DBIxClass. It was generated by Bigtop, but is
NOT subject to regeneration.
=cut
[% END %]
[% BLOCK gen_three_way_gen_module %]
# NEVER EDIT this file. It was generated and will be overwritten without
# notice upon regeneration of this application. You have been warned.
package [% stub_package %];
use strict; use warnings;
__PACKAGE__->load_components( qw/ PK::Auto Core / );
__PACKAGE__->table( '[% table_name %]' );
__PACKAGE__->add_columns( qw/
id
[% FOREACH other_table IN joined_tables %]
[% other_table +%]
[% END %]
[% FOREACH extra IN extra_fields %]
[% extra +%]
[% END %]
/ );
__PACKAGE__->set_primary_key( 'id' );
__PACKAGE__->base_model( '[% app_name %]::Model' );
[% FOREACH other_table IN joined_tables %]
__PACKAGE__->belongs_to( [% other_table %] => '[% app_name %]::Model::[% other_table %]' );
[% END %]
sub get_foreign_tables {
return qw(
);
}
sub table_name {
return '[% table_name %]';
}
[% IF option_fields.0 +%]
[% extra_methods = [] %]
my %select_map_for = (
[% FOREACH option_field IN option_fields %]
[% option_field.name %] => {
[% FOREACH option IN option_field.options %]
[% option.db_value %] => '[% option.label %]',
[% END %]
},
[% END %]
);
[% FOREACH option_field IN option_fields %]
[% meth_name = option_field.name;
extra_methods.push( "${meth_name}_display" ) %]
sub [% option_field.name %]_display {
my $self = shift;
return $select_map_for{ [% option_field.name %] }{ $self->[% option_field.name %] }
|| $self->[% option_field.name %];
}
[% END %]
[% END %]
1;
=head1 NAME
[% gen_package %] - model for [% table_name %] table (generated part)
=head1 DESCRIPTION
This model inherits from Gantry::Utils::DBIxClass.
It was generated by Bigtop, and IS subject to regeneration.
=head1 METHODS
You may use all normal Gantry::Utils::DBIxClass methods and the
ones listed here:
=over 4
=item get_foreign_display_fields
=item get_foreign_tables
=item foreign_display
=item table_name
[% FOREACH extra_method IN extra_methods %]
=item [% extra_method +%]
[% END %]
=back
=cut
[% END %]
EO_TT_blocks
#-----------------------------------------------------------------
# Methods in the Bigtop::Model::GantryDBIxClass package
#-----------------------------------------------------------------
sub what_do_you_make {
return [
[ 'lib/AppName/Model/*.pm' =>
'DBIx::Class style model stubs [safe to change]' ],
[ 'lib/AppName/Model/GEN/*.pm' =>
'DBIx::Class style model specifications [please, do not change]' ],
[ 'note' =>
'This backend requires "For use with DBIx::Class" to be checked '
. 'for the Control Gantry backend.' ],
[ 'note' =>
'This backend is incompatible with other Model backends.' ],
];
}
sub backend_block_keywords {
return [
{ keyword => 'no_gen',
label => 'No Gen',
descr => 'Skip everything for this backend',
type => 'boolean' },
{ keyword => 'model_base_class',
label => 'Models Inherit From',
descr => 'Defaults to Gantry::Utils::DBIxClass',
type => 'text' },
{ keyword => 'template',
label => 'Alternate Template',
descr => 'A custom TT template.',
type => 'text' },
{ keyword => 'extra_components',
label => 'Extras for load_components',
descr => 'Things other than PK::Auto and Core to load. '
. 'Separate multiples with spaces.',
type => 'text' },
];
}
sub setup_template {
my $class = shift;
my $template_text = shift || $default_template_text;
return if ( $template_is_setup );
Inline->bind(
TT => $template_text,
POST_CHOMP => 1,
TRIM_LEADING_SPACE => 0,
TRIM_TRAILING_SPACE => 0,
);
$template_is_setup = 1;
}
sub gen_Model {
my $class = shift;
my $build_dir = shift;
my $bigtop_tree = shift;
# make sure the directories are ready for us
my $app_base_name = $bigtop_tree->get_appname();
my $model_name = $app_base_name . '::Model';
my ( $module_dir, @sub_dirs )
= Bigtop::make_module_path( $build_dir, $model_name );
my $gen_dir = File::Spec->catdir( $module_dir, 'GEN' );
mkdir $gen_dir;
# see if there is an alternate default base module
my $config_block = $bigtop_tree->get_config()->{Model};
# build the individual model packages
my $child_models = $bigtop_tree->walk_postorder(
'output_dbix_model',
{
app_name => $app_base_name,
module_dir => $module_dir,
model_name => $model_name,
lookup => $bigtop_tree->{application}{lookup},
model_base_class => $config_block->{model_base_class}
|| 'Gantry::Utils::DBIxClass',
extra_components => $config_block->{extra_components},
},
);
$bigtop_tree->walk_postorder(
'output_join_modules_dbix',
{
app_name => $app_base_name,
module_dir => $module_dir,
model_name => $model_name,
lookup => $bigtop_tree->{application}{lookup},
model_base_class => $config_block->{model_base_class}
|| 'Gantry::Utils::DBIxClass',
}
);
my $year = ( localtime )[5] + 1900;
my $gen_base_model =
Bigtop::Backend::Model::GantryDBIxClass::gen_base_model(
{
app_name => $app_base_name,
table_models => $child_models,
authors => $bigtop_tree->get_authors(),
year => $year,
copyright_holder => $bigtop_tree->get_copyright_holder(),
license_text => $bigtop_tree->get_license_text(),
}
);
my $base_model = Bigtop::Backend::Model::GantryDBIxClass::stub_base_model(
{
app_name => $app_base_name,
table_models => $child_models,
authors => $bigtop_tree->get_authors(),
year => $year,
copyright_holder => $bigtop_tree->get_copyright_holder(),
license_text => $bigtop_tree->get_license_text(),
}
);
my ( $base_dir ) = Bigtop::make_module_path( $build_dir, $app_base_name );
my $base_file = File::Spec->catfile( $base_dir, 'Model.pm' );
my $gen_file = File::Spec->catfile( $base_dir, 'GENModel.pm' );
Bigtop::write_file( $gen_file, $gen_base_model );
no warnings qw( Bigtop );
Bigtop::write_file( $base_file, $base_model, 'no overwrite' );
}
#-----------------------------------------------------------------
# Packages named in the grammar
#-----------------------------------------------------------------
package # table_block
table_block;
use strict; use warnings;
sub output_dbix_model {
my $self = shift;
my $child_output = shift;
my $data = shift;
my @option_fields;
while ( @{ $child_output } ) {
my $field_name = shift @{ $child_output };
my $options = shift @{ $child_output };
push @option_fields, {
name => $field_name,
options => $options,
};
}
# Skip sequences, etc.
return unless ( $self->{__TYPE__} =~ /tables/ );
my $table_lookup = $data->{lookup}{tables}{ $self->{__NAME__} };
my $grand_parent = $self->{__PARENT__}{__PARENT__};
if ( $table_lookup->{not_for} ) {
foreach my $skipped_type ( @{ $table_lookup->{not_for}{__ARGS__} } ) {
return if ( $skipped_type eq 'Model' );
}
}
# get columns sets
my $lookup = $table_lookup->{fields};
my $regular_accessor_columns = $self->walk_postorder(
'output_regular_accessors_dbix', $lookup
);
my $special_accessor_columns = $self->walk_postorder(
'output_special_accessors_dbix', $lookup
);
my $add_columns = $self->walk_postorder(
'output_add_columns_dbix', $lookup
);
my $essentials = $self->walk_postorder(
'output_essential_fields_dbix', $lookup
);
# deal with foreign keys
my $foreign_tables = $self->walk_postorder(
'output_foreign_tables_dbix', $lookup
);
# deal with foreign keys pointing toward this table
my $has_manys = $self->walk_postorder(
'output_has_manys', $data->{lookup}->{tables}
);
my @foreign_table_names;
my @has_a_list;
foreach my $entry ( @{ $foreign_tables } ) {
my $entry_hash = { @{ $entry } };
push @foreign_table_names, $entry_hash->{table};
push @has_a_list, $entry_hash;
}
# deal with 3 way joins
my $three_ways = $grand_parent->walk_postorder(
'output_has_manys_dbix',
{
lookup => $data->{lookup}{join_tables},
model => $data->{model_name},
table => $self->{__NAME__},
}
);
# Gone Fishing.
my $table = $self->{__NAME__};
$table =~ s/\./_/;
my $module_name = $data->{model_name} . '::' . $table;
my $gen_pack_name = $data->{model_name} . '::GEN::' . $table;
my $alias = uc $table;
my $sequence = $table_lookup->{sequence};
my $foreign_display = $table_lookup->{foreign_display};
my $sequence_name;
if ( $sequence ) {
$sequence_name = $sequence->{__ARGS__}[0];
}
my $primary_key = $self->find_primary_key(
$self->{__NAME__},
$data->{ lookup },
);
my $unique_name = $self->find_unique_name(
$self->{__NAME__},
$data->{ lookup },
);
my $foreign_display_columns;
my $foreign_display_body;
if ( $foreign_display ) {
my $foreign_display_cols = $foreign_display->{__ARGS__}[0];
my @field_names = ( $foreign_display_cols =~ /%([\w\d_]*)/g );
$foreign_display_columns = "@field_names";
$foreign_display_body = _build_foreign_display_body(
$foreign_display_cols, @field_names
);
}
my $base_class;
if ( defined $table_lookup->{model_base_class} ) {
$base_class = $table_lookup->{model_base_class}{__ARGS__}[0];
}
# generate output
my $stub_content =
Bigtop::Backend::Model::GantryDBIxClass::stub_table_module(
{
base_class => $base_class,
base_class_default => $data->{model_base_class},
base_package_name => $data->{model_name},
gen_package_name => $gen_pack_name,
package_name => $module_name,
package_alias => $alias,
table_name => $table,
option_fields => \@option_fields,
}
);
my $pk_auto = 1;
if ( not defined $primary_key or ref( $primary_key ) eq 'ARRAY' ) {
$pk_auto = 0;
}
my @load_components = ( 'Core' );
if ( defined $data->{ extra_components }
and
$data->{ extra_components } =~ /InflateColumn::DateTime/
) {
unshift @load_components, $data->{ extra_components };
}
elsif ( $pk_auto ) {
unshift @load_components, 'PK::Auto';
}
my $load_components = join ' ', @load_components;
my $gen_content =
Bigtop::Backend::Model::GantryDBIxClass::gen_table_module(
{
base_class_default => $data->{model_base_class},
base_package_name => $data->{model_name},
package_name => $module_name,
gen_package_name => $gen_pack_name,
package_alias => $alias,
table_name => $table,
sequence_name => $sequence_name,
primary_key => $primary_key,
unique_name => $unique_name,
load_components => $load_components,
foreign_display_columns => $foreign_display_columns,
foreign_display_body => $foreign_display_body,
regular_accessor_columns=> $regular_accessor_columns,
special_accessor_columns=> $special_accessor_columns,
add_columns => $add_columns,
essential_columns => $essentials,
has_a_list => \@has_a_list,
has_manys => $has_manys,
three_ways => $three_ways,
foreign_tables => \@foreign_table_names,
app_name => $data->{ app_name },
real_table_name => $self->{__NAME__},
option_fields => \@option_fields,
}
);
# store it
my $module_file = File::Spec->catfile( $data->{module_dir}, "$table.pm" );
my $gen_dir = File::Spec->catdir ( $data->{module_dir}, 'GEN' );
my $gen_file = File::Spec->catfile( $gen_dir, "$table.pm" );
eval {
no warnings qw( Bigtop );
Bigtop::write_file( $module_file, $stub_content, 'no overwrite' );
};
warn $@ if $@;
eval {
Bigtop::write_file( $gen_file, $gen_content );
};
warn $@ if $@;
return [ $table ];
}
package # table_element_block
table_element_block;
use strict; use warnings;
sub output_regular_accessors_dbix {
my $self = shift;
shift;
my $data = shift;
return unless ( ref( $self->{__BODY__} ) );
my $field = $data->{ $self->{__NAME__} };
return if ( _not_for_model( $field ) );
return if $field->{ pseudo_value };
return if ( defined $field->{ accessor }
or
defined $field->{ add_columns } );
return [ $self->{__NAME__} ];
}
sub output_special_accessors_dbix {
my $self = shift;
shift;
my $data = shift;
return unless ( ref( $self->{__BODY__} ) );
my $field = $data->{ $self->{__NAME__} };
return unless ( defined $field->{ accessor } );
my $special_accessor_name = $field->{ accessor }{ args }->get_first_arg();
return [
{
name => $self->{__NAME__},
accessor => $special_accessor_name,
}
];
}
sub output_add_columns_dbix {
my $self = shift;
shift;
my $data = shift;
return unless ( ref( $self->{__BODY__} ) );
my $field = $data->{ $self->{__NAME__} };
return unless ( defined $field->{ add_columns } );
my $args = $field->{ add_columns }{ args };
my @pairs;
foreach my $col ( @{ $args } ) {
my ( $key, $value ) = %{ $col };
push @pairs, { key => $key, value => $value };
}
return [
{
name => $self->{__NAME__},
pairs => \@pairs,
}
];
}
sub output_essential_fields_dbix {
my $self = shift;
shift;
my $data = shift;
return unless ( ref( $self->{__BODY__} ) );
my $field = $data->{ $self->{__NAME__} };
if ( $field->{non_essential} ) {
my $non_essential_value = $field->{non_essential}{args}[0];
return if ( $non_essential_value );
}
return if ( _not_for_model( $field ) );
return [ $self->{__NAME__} ];
}
sub output_foreign_tables_dbix {
my $self = shift;
shift;
my $data = shift;
return unless ( ref( $self->{__BODY__} ) );
my $field = $data->{ $self->{__NAME__} };
if ( $field->{refers_to} ) {
my $foreign_table_name = $field->{refers_to}{args}[0];
if ( ref( $foreign_table_name ) eq 'HASH' ) {
( $foreign_table_name ) = %{ $foreign_table_name };
}
$foreign_table_name =~ s/\./_/;
return [
[ column => $self->{__NAME__}, table => $foreign_table_name ]
];
}
return;
}
sub output_has_manys {
my $self = shift;
shift;
my $data = shift;
return unless ( $self->{__TYPE__} eq 'refered_to_by' );
my @retval;
foreach my $arg ( @{ $self->{__ARGS__} } ) {
my ( $refering_table, $has_many_name, $field_name );
if ( ref( $arg ) eq 'HASH' ) {
( $refering_table, $has_many_name ) = %{ $arg };
}
else {
( $refering_table, $has_many_name ) = ( $arg, $arg . 's' );
}
# Get the name of the field in the table that is refering to this one.
FIELD_SEARCH:
foreach my $field ( %{ $data->{$refering_table}->{fields} } ) {
if ( $data->{$refering_table}->{fields}->{$field}->{refers_to} ) {
foreach my $refers_to_arg ( @{ $data->{$refering_table}->{fields}->{$field}->{refers_to}->{args} } ) {
my $refered_to_table;
if ( ref( $refers_to_arg ) eq 'HASH' ) {
( $refered_to_table, undef ) = %{ $refers_to_arg };
}
else {
$refered_to_table = $refers_to_arg;
}
if ( $refered_to_table eq $self->{__PARENT__}->{__NAME__}) {
$field_name = $field;
last FIELD_SEARCH;
}
}
}
}
push @retval, { name => $has_many_name, table => $refering_table, field => $field_name };
}
return \@retval;
}
sub output_join_modules_dbix {
my $self = shift;
my $child_output = shift;
push @{ $child_output }, { plain_field => $self->get_name };
return $child_output;
}
package # join_table
join_table;
use strict; use warnings;
sub output_dbix_model {
my $self = shift;
my $child_output = shift;
my $data = shift;
return [ $self->{__NAME__} ];
}
# warn "im a join table ($self->{__NAME__}) and i veto\n";
# use Data::Dumper; warn Dumper( $child_output );
sub output_join_modules_dbix {
my $self = shift;
my $child_output = shift;
my $data = shift;
my $table = $self->{__NAME__};
my @foreign_keys;
my @option_fields;
my @extra_fields;
foreach my $tidbit ( @{ $child_output } ) {
if ( ref $tidbit eq 'ARRAY' ) {
while ( @{ $tidbit->[0] } ) {
my $field_name = shift @{ $tidbit->[0] };
my $options = shift @{ $tidbit->[0] };
push @option_fields, {
name => $field_name,
options => $options,
};
}
}
elsif ( ref $tidbit eq 'HASH' ) {
my ( undef, $plain_field ) = %{ $tidbit };
push @extra_fields, $plain_field;
}
else {
push @foreign_keys, $tidbit;
}
}
my $package = join '::', $data->{model_name}, $self->{__NAME__};
my $gen_package = join '::',
$data->{model_name}, 'GEN', $self->{__NAME__};
my $module_file = File::Spec->catfile( $data->{module_dir}, "$table.pm" );
my $gen_file = File::Spec->catfile(
$data->{module_dir}, 'GEN', "$table.pm"
);
my $stub_content =
Bigtop::Backend::Model::GantryDBIxClass::gen_three_way_module(
{
stub_package => $package,
gen_package => $gen_package,
table_name => $table,
model_base_class => $data->{model_base_class},
package_alias => uc $table,
}
);
eval {
no warnings qw( Bigtop );
Bigtop::write_file( $module_file, $stub_content, 'no overwrite' );
};
warn $@ if $@;
my $gen_content =
Bigtop::Backend::Model::GantryDBIxClass::gen_three_way_gen_module(
{
app_name => $data->{app_name},
stub_package => $package,
gen_package => $gen_package,
table_name => $table,
model_base_class => $data->{model_base_class},
package_alias => uc $table,
joined_tables => \@foreign_keys,
option_fields => \@option_fields,
extra_fields => \@extra_fields,
}
);
eval {
Bigtop::write_file( $gen_file, $gen_content );
};
warn $@ if $@;
return [ 1 ];
}
package # join_table_statement
join_table_statement;
use strict; use warnings;
sub output_has_manys_dbix {
my $self = shift;
my $child_output = shift;
my $data = shift;
return unless $self->{__KEYWORD__} eq 'joins';
my $join_table_name = $self->get_join_table_name();
my @tables = %{ $self->{__DEF__}->get_first_arg() };
unless ( $tables[0] eq $data->{table}
or
$tables[1] eq $data->{table}
) {
return;
}
my $lookup = $data->{ lookup }{ $data->{ table } };
CANDIDATE:
foreach my $candidate ( @{ $lookup } ) {
if ( defined $candidate->{ joins } ) {
my ( $foreign_key, $third_table ) = %{ $candidate->{ joins } };
next CANDIDATE unless ( $third_table eq $join_table_name );
my $foreign_name;
if ( defined $candidate->{ name } ) {
$foreign_name = $candidate->{ name };
}
else {
$foreign_name = $foreign_key . 's';
}
return [ {
join_name => $third_table . 's',
three_way_model => "$data->{ model }::$third_table",
current_table => $data->{ table },
foreign_name => $foreign_name,
foreign_key => $foreign_key,
} ];
}
}
return;
}
sub output_join_modules_dbix {
my $self = shift;
my $child_output = shift;
my $data = shift;
return unless $self->{__KEYWORD__} eq 'joins';
my @tables = %{ $self->{__DEF__}->get_first_arg() };
return \@tables;
}
package # field_statement
field_statement;
use strict; use warnings;
sub output_dbix_model {
my $self = shift;
return unless $self->{__KEYWORD__} eq 'html_form_options';
my $name = $self->get_field_name;
my @tt_options;
foreach my $option ( @{ $self->{__DEF__}{__ARGS__} } ) {
my %tt_option;
( $tt_option{ label }, $tt_option{ db_value } ) = %{ $option };
push @tt_options, \%tt_option;
}
return [ $name, \@tt_options ];
}
sub output_join_modules_dbix {
my $self = shift;
my $option_output = $self->output_dbix_model( );
return unless $option_output;
return [ [ $option_output ] ];
}
1;
__END__
=head1 NAME
Bigtop::Backend::Model::GantryDBIxClass - Bigtop backend generating DBIx::Class models
=head1 SYNOPSIS
If your bigtop file looks like this:
config {
base_dir `/home/user`;
...
Model GantryDBIxClass {}
}
app Name {...}
and there are tables in the app block, when you type:
bigtop your.bigtop Model
or
bigtop your.bigtop all
this module will make model modules which are subclasses of
Gantry::Utils::DBIxClass (which inherits from DBIx::Class).
All modules will live in the lib subdirectory of the app's build directory.
See Bigtop::Init::Std for an explanation of how base_dir and the
build directory are related.
=head1 DESCRIPTION
This is a Bigtop backend which generates data model modules which are
subclasses of Gantry::Utils::DBIxClass.
=head1 KEYWORDS
This module does not register any keywords. See Bigtop::Model for
a list of keywords models understand.
The default for the model_base_class keyword is Gantry::Utils::DBIxClass.
=head1 METHODS
To keep podcoverage tests happy.
=over 4
=item backend_block_keywords
Tells tentmaker that I understand these config section backend block keywords:
no_gen
model_base_class
template
=item what_do_you_make
Tells tentmaker what this module makes. Summary: DBIx::Class models and
schema.
=item gen_Model
Called by Bigtop::Parser to get me to do my thing.
=item setup_template
Called by Bigtop::Parser so the user can substitute an alternate template
for the hard coded one here.
=back
=head1 AUTHOR
Phil Crow <crow.phil@gmail.com>
=head1 COPYRIGHT and LICENSE
Copyright (C) 2005 by 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.
=cut