NAME

DBIx::Class::Factory - factory-style fixtures for DBIx::Class

VERSION

Version 0.03

SYNOPSIS

Create factory:

package My::UserFactory;
use base qw(DBIx::Class::Factory);

__PACKAGE__->resultset(My::Schema->resultset('User'));
__PACKAGE__->fields({
    name => __PACKAGE__->seq(sub {'User #' . shift}),
    status => 'new',
});

package My::SuperUserFactory;
use base qw(DBIx::Class::Factory);

__PACKAGE__->base_factory('My::UserFactory');
__PACKAGE__->field(superuser => 1);

Use factory:

my $user = My::UserFactory->create();
my @verified_users = @{ My::UserFactory->create_batch(3, {status => 'verified'}) };

my $superuser = My::SuperUserFactory->build();
$superuser->insert();

DESCRIPTION

Ruby has factory_girl, Python has factory_boy. Now Perl has DBIx::Class::Factory.

Creating big fixture batches may be a pain. This module provides easy way of creating data in database via DBIx::Class.

To create a factory just derive from DBIx::Class::Factory and apply some settings. You can also add some data at the moment of creating instance, redefining factory defaults.

Tests for this module contains a bunch of usefull examples.

METHODS

Factory settings

base_factory

Use this to create one factory derived from another. Don't use direct inheritance.

resultset

Set resultset this factory is going to work with.

fields

Accept hashref as an argument. Add fields to factory. See "field" for more details.

field
__PACKAGE__->field($name => $value);

Add field to the factory. $name is directly used in resultset's new method. $value must be any value or helper result (see "Helpers"). CODEREF as a value will be used as callback. However, you must not rely on this, it can be changed in future releases — use "callback" helper instead.

exclude

Sometimes you want some fields to be in the factory but not in the created object.

You can use exclude to exclude them. Both arrayref and scalar are accepted.

{
    package My::UserFactory;

    use base qw(DBIx::Class::Factory);

    __PACKAGE__->resultset(My::Schema->resultset('User'));
    __PACKAGE__->exclude('all_names');
    __PACKAGE__->fields({
        first_name => __PACKAGE__->callback(sub {shift->get('all_names')}),
        last_name => __PACKAGE__->callback(sub {shift->get('all_names')}),
    });
}

My::UserFactory->create({all_names => 'Bond'});

Helpers

Sometimes you want the value of the field to be not just static value but something special. Helpers are here for that.

callback

Sometimes you want field value to be calculated everytime fields for object are created. Just provide callback as a value in that case.

It will be called with the DBIx::Class::Factory::Fields instance as an argument.

__PACKAGE__->fields({
    status => __PACKAGE__->callback(sub {
        my ($fields) = @_;

        return $fields->get('superuser') ? 3 : 5;
    }),
});
seq

Same as "callback", but the callback is called with an additional first argument: the iterating counter.

You can also provide the initial value of the counter (0 is default).

__PACKAGE__->field(id => __PACKAGE__->seq(sub {shift}, 1));

This helper just calls another factory's "get_fields" method. Thanks to DBIx::Class, the returned data will be used to create a related object.

package My::UserFactory;

use base qw(DBIx::Class::Factory);

__PACKAGE__->resultset(My::Schema->resultset('User'));
__PACKAGE__->fields({
    # create a new city if it's not specified
    city => __PACKAGE__->related_factory('My::CityFactory'),
});

Same as "related_factory", but calls "get_fields_batch" method.

__PACKAGE__->fields({
    # Add three accounts to the user
    accounts => __PACKAGE__->related_factory_batch(3, 'My::AccountFactory')
});

Factory actions

get_fields

Returns fields that will be used to create object without creating something.

build

Creates DBIx::Class::Row object without saving it to a database.

create

Creates DBIx::Class::Row object and saves it to a database.

You can also provide the second argument, hashref of options. The only option is discard_changes, a boolean value which default is true. It says whether "discard_changes" in DBIx::Class::Row should be called on the created object.

My::UserFactory->create(undef, {discard_changes => 0}); 
get_fields_batch

Runs "get_fields" n times and returns arrayref of results.

build_batch

Runs "build" n times and returns arrayref of results.

create_batch

Runs "create" n times and returns arrayref of results.

Hooks

You can define the following methods in your factory to be executed after corresponding methods.

They take result of the corresponding methods as an argument and must return the new one.

after_get_fields
after_build
after_create
sub after_create {
    my ($class, $user_row) = @_;

    $user_row->auth();

    return $user_row;
}

AUTHOR

Vadim Pushtaev, pushtaev@cpan.org

BUGS AND FEATURES

Bugs are possible, feature requests are welcome. Write me as soon as possible.

LICENSE AND COPYRIGHT

Copyright 2015 Vadim Pushtaev.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.