| Bigtop documentation | Contained in the Bigtop distribution. |
Bigtop::Backend::Model::GantryDBIxClass - Bigtop backend generating DBIx::Class models
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.
This is a Bigtop backend which generates data model modules which are subclasses of Gantry::Utils::DBIxClass.
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.
To keep podcoverage tests happy.
Tells tentmaker that I understand these config section backend block keywords:
no_gen
model_base_class
template
Tells tentmaker what this module makes. Summary: DBIx::Class models and schema.
Called by Bigtop::Parser to get me to do my thing.
Called by Bigtop::Parser so the user can substitute an alternate template for the hard coded one here.
Phil Crow <crow.phil@gmail.com>
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.
| Bigtop documentation | Contained in the Bigtop distribution. |
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__