DBIx-Class-Schema-Loader

 view release on metacpan or  search on metacpan

lib/DBIx/Class/Schema/Loader/RelBuilder.pm  view on Meta::CPAN

package DBIx::Class::Schema::Loader::RelBuilder;

use strict;
use warnings;
use base 'Class::Accessor::Grouped';
use mro 'c3';
use Carp::Clan qw/^DBIx::Class/;
use Scalar::Util 'weaken';
use DBIx::Class::Schema::Loader::Utils qw/split_name slurp_file array_eq apply uniq/;
use Try::Tiny;
use List::Util qw/all any first/;
use namespace::clean;
use Lingua::EN::Inflect::Phrase ();
use Lingua::EN::Tagger ();
use String::ToIdentifier::EN ();
use String::ToIdentifier::EN::Unicode ();
use Class::Unload ();
use Class::Inspector ();

our $VERSION = '0.07053';

# Glossary:
#
# local_relname  -- name of relationship from the local table referring to the remote table
# remote_relname -- name of relationship from the remote table referring to the local table
# remote_method  -- relationship type from remote table to local table, usually has_many

=head1 NAME

DBIx::Class::Schema::Loader::RelBuilder - Builds relationships for DBIx::Class::Schema::Loader

=head1 SYNOPSIS

See L<DBIx::Class::Schema::Loader> and L<DBIx::Class::Schema::Loader::Base>.

=head1 DESCRIPTION

This class builds relationships for L<DBIx::Class::Schema::Loader>.  This
is module is not (yet) for external use.

=head1 METHODS

=head2 new

Arguments: $loader object

=head2 generate_code

Arguments:

    [
        [ local_moniker1 (scalar), fk_info1 (arrayref), uniq_info1 (arrayref) ]
        [ local_moniker2 (scalar), fk_info2 (arrayref), uniq_info2 (arrayref) ]
        ...
    ]

This generates the code for the relationships of each table.

C<local_moniker> is the moniker name of the table which had the REFERENCES
statements.  The fk_info arrayref's contents should take the form:

    [
        {
            local_table    => 'some_table',
            local_moniker  => 'SomeTable',
            local_columns  => [ 'col2', 'col3' ],
            remote_table   => 'another_table_moniker',
            remote_moniker => 'AnotherTableMoniker',

lib/DBIx/Class/Schema/Loader/RelBuilder.pm  view on Meta::CPAN

        ],
        [
            another_uniq_constraint_name => [ 'col1', 'col2' ],
        ],
    ],

This method will return the generated relationships as a hashref keyed on the
class names.  The values are arrayrefs of hashes containing method name and
arguments, like so:

    {
        'Some::Source::Class' => [
            { method => 'belongs_to', arguments => [
              'col1', 'Another::Source::Class' ] },
            { method => 'has_many', arguments => [
              'anothers', 'Yet::Another::Source::Class', 'col15' ] },
        ],
        'Another::Source::Class' => [
            # ...
        ],
        # ...
    }

=cut

__PACKAGE__->mk_group_accessors('simple', qw/
    loader
    schema
    inflect_plural
    inflect_singular
    relationship_attrs
    rel_collision_map
    rel_name_map
    allow_extra_m2m_cols
    _temp_classes
    __tagger
/);

sub new {
    my ($class, $loader) = @_;

    # from old POD about this constructor:
    # C<$schema_class> should be a schema class name, where the source
    # classes have already been set up and registered.  Column info,
    # primary key, and unique constraints will be drawn from this
    # schema for all of the existing source monikers.

    # Options inflect_plural and inflect_singular are optional, and
    # are better documented in L<DBIx::Class::Schema::Loader::Base>.

    my $self = {
        loader             => $loader,
        (map { $_ => $loader->$_ } qw(
            schema inflect_plural inflect_singular
            relationship_attrs rel_collision_map
            rel_name_map allow_extra_m2m_cols
        )),
        _temp_classes      => [],
    };

    weaken $self->{loader}; #< don't leak

    bless $self => $class;

    # validate the relationship_attrs arg
    if( defined $self->relationship_attrs ) {
        (ref $self->relationship_attrs eq 'HASH' || ref $self->relationship_attrs eq 'CODE')
            or croak "relationship_attrs must be a hashref or coderef";
    }

    return $self;
}


# pluralize a relationship name
sub _inflect_plural {
    my ($self, $relname) = @_;

    return '' if !defined $relname || $relname eq '';

    my $result;
    my $mapped = 0;

    if( ref $self->inflect_plural eq 'HASH' ) {
        if (exists $self->inflect_plural->{$relname}) {
            $result = $self->inflect_plural->{$relname};
            $mapped = 1;
        }
    }
    elsif( ref $self->inflect_plural eq 'CODE' ) {
        my $inflected = $self->inflect_plural->($relname);
        if ($inflected) {
            $result = $inflected;
            $mapped = 1;
        }
    }

    return ($result, $mapped) if $mapped;

    return ($self->_to_PL($relname), 0);
}

# Singularize a relationship name
sub _inflect_singular {
    my ($self, $relname) = @_;

    return '' if !defined $relname || $relname eq '';

    my $result;
    my $mapped = 0;

    if( ref $self->inflect_singular eq 'HASH' ) {
        if (exists $self->inflect_singular->{$relname}) {
            $result = $self->inflect_singular->{$relname};
            $mapped = 1;
        }
    }
    elsif( ref $self->inflect_singular eq 'CODE' ) {
        my $inflected = $self->inflect_singular->($relname);
        if ($inflected) {
            $result = $inflected;



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