Alzabo

 view release on metacpan or  search on metacpan

lib/Alzabo/MethodMaker.pm  view on Meta::CPAN

            ) or next;

        $self->{row_class}->add_method_docs
            ( Alzabo::MethodDocs->new
              ( name  => $name,
                group => 'Methods that update/return a column value',
                spec  => [ { type => SCALAR } ],
                description =>
                "returns the value of the " . $c->name . " column for a row.  Given a value, it will also update the row first.",
              ) );
    }
}

sub make_foreign_key_methods
{
    my $self = shift;
    my $t = shift;

    foreach my $other_t ( sort { $a->name cmp $b->name  } $t->schema->tables )
    {
        my @fk = $t->foreign_keys_by_table($other_t)
            or next;

        if ( @fk == 2 && $fk[0]->table_from eq $fk[0]->table_to &&
             $fk[1]->table_from eq $fk[1]->table_to )
        {
            unless ($fk[0]->is_one_to_one)
            {
                $self->make_self_relation($fk[0]) if $self->{opts}{self_relations};
            }
            next;
        }

        foreach my $fk (@fk)
        {
            $self->_make_fk_method($fk);
        }
    }
}

sub _make_method
{
    my $self = shift;
    my %p = validate @_, { type => { type => SCALAR },
                           class => { type => SCALAR },
                           returns => { type => SCALAR, optional => 1 },
                           code => { type => CODEREF },

                           # Stuff we can pass through to name_maker
                           foreign_key => { optional => 1 },
                           foreign_key_2 => { optional => 1 },
                           column => { optional => 1 },
                           table => { optional => 1 },
                           parent => { optional => 1 },
                           plural => { optional => 1 },
                         };

    my $name = $self->{opts}{name_maker}->( %p )
        or return;

    my ($code_name, $debug_name) = ("$p{class}::$name",
                                    "$p{class}\->$name");

    if ( $p{class}->can($name) )
    {
        warn "MethodMaker: Creating $p{type} method $debug_name will override"
             . " the method of the same name in the parent class\n";
    }

    no strict 'refs';  # We use symbolic references here
    if ( defined &$code_name )
    {
        # This should probably always be shown to the user, not just
        # when debugging mode is turned on, because name clashes can
        # cause confusion - whichever subroutine happens first will
        # arbitrarily win.

        warn "MethodMaker: skipping $p{type} method $debug_name, subroutine already exists\n";
        return;
    }

    if (Alzabo::Debug::METHODMAKER)
    {
        my $message = "Making $p{type} method $debug_name";
        $message .= ": returns $p{returns}" if $p{returns};
        print STDERR "$message\n";
    }

    *$code_name = $p{code};
    return $name;
}

sub _make_fk_method
{
    my $self = shift;
    my $fk = shift;
    my $table_to = $fk->table_to->name;

    # The table may be a linking or lookup table.  If we are
    # supposed to make that kind of method we will and then we'll
    # skip to the next foreign table.
    $self->make_linking_table_method($fk)
        if $self->{opts}{linking_tables};

    $self->make_lookup_columns_methods($fk)
        if $self->{opts}{lookup_columns};

    return unless $self->{opts}{foreign_keys};

    if ($fk->is_one_to_many)
    {
        my $name = $self->_make_method
            ( type => 'foreign_key',
              class => $self->{row_class},
              returns => 'row cursor',
              code => sub { my $self = shift;
                            return $self->rows_by_foreign_key( foreign_key => $fk, @_ ); },
              foreign_key => $fk,
              plural => 1,
            ) or return;

        $self->{row_class}->add_method_docs
            ( Alzabo::MethodDocs->new
              ( name  => $name,
                group => 'Methods that return cursors for foreign keys',
                description =>
                "returns a cursor containing related rows from the " . $fk->table_to->name . " table",
                spec  => 'same as Alzabo::Runtime::Table->rows_where',
              ) );
    }
    # Singular method name
    else
    {
        my $name = $self->_make_method
            ( type => 'foreign_key',
              class => $self->{row_class},
              returns => 'single row',
              code => sub { my $self = shift;
                            return $self->rows_by_foreign_key( foreign_key => $fk, @_ ); },
              foreign_key => $fk,
              plural => 0,
            ) or return;

        $self->{row_class}->add_method_docs



( run in 0.529 second using v1.01-cache-2.11-cpan-39bf76dae61 )