DBIx-QuickORM

 view release on metacpan or  search on metacpan

t/AI/row_state.t  view on Meta::CPAN

use Test2::V0;
use DBI;
use File::Temp qw/tempdir/;

# Exercises the row state model documented in DBIx::QuickORM::Row,
# DBIx::QuickORM::Role::Row, and DBIx::QuickORM::Connection::RowData:
# stored vs pending vs inflated/raw views, save/discard/update/refresh,
# delete, the storage/validity predicates, the field-hash views, clone,
# and the primary-key helpers.

BEGIN {
    skip_all "DBD::SQLite is required for these tests"
        unless eval { require DBD::SQLite; 1 };
}

require DBIx::QuickORM;

my $dir  = tempdir(CLEANUP => 1);
my $file = "$dir/row_state.sqlite";
my $dsn  = "dbi:SQLite:dbname=$file";

{
    my $dbh = DBI->connect($dsn, '', '', {RaiseError => 1, PrintError => 0});
    $dbh->do('CREATE TABLE users (user_id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT, meta_json TEXT)');
    $dbh->do('INSERT INTO users (name, email, meta_json) VALUES (?, ?, ?)', undef, 'bob', 'bob@example.com', '{"age":42}');
    $dbh->disconnect;
}

# Read a column straight from the database, bypassing the ORM and any
# row cache, so we can verify what was actually persisted.
sub db_value {
    my ($col, $pk) = @_;
    my $dbh = DBI->connect($dsn, '', '', {RaiseError => 1, PrintError => 0});
    my ($val) = $dbh->selectrow_array("SELECT $col FROM users WHERE user_id = ?", undef, $pk);
    $dbh->disconnect;
    return $val;
}

my $con = DBIx::QuickORM->quick(credentials => {dsn => $dsn}, auto_types => ['JSON']);
isa_ok($con, ['DBIx::QuickORM::Connection'], "got a live Connection");

my $bob = $con->handle('users')->where({name => 'bob'})->one;
my $bob_pk = $bob->field('user_id');
ok(defined($bob_pk), "fetched bob and have a primary key");

subtest field_get_set_and_pending => sub {
    ok($bob->is_stored, "freshly fetched row is stored");
    ok($bob->in_storage, "freshly fetched row is in_storage");
    ok($bob->is_valid, "freshly fetched row is valid");
    ok(!$bob->is_invalid, "freshly fetched row is not invalid");
    ok(!$bob->has_pending, "no pending changes after fetch");

    is($bob->field('name'), 'bob', "field() returns the stored value");

    $bob->field(name => 'robert');
    ok($bob->has_pending, "setting a field stages a pending change");
    is($bob->field('name'), 'robert', "field() reflects the pending value");
    is($bob->stored_field('name'), 'bob', "stored_field() still shows the original db value");

    # Database is untouched until save.
    is(db_value(name => $bob_pk), 'bob', "database row unchanged before save");

    $bob->save;
    ok(!$bob->has_pending, "save() clears pending");
    is($bob->field('name'), 'robert', "value persists in the row after save");
    is(db_value(name => $bob_pk), 'robert', "save() wrote the change to the database");

    # Reset for later subtests.
    $bob->update({name => 'bob'});
    is(db_value(name => $bob_pk), 'bob', "reset name back to bob");
};

subtest modify_now_save_later => sub {
    $bob->field(name  => 'robert');
    $bob->field(email => 'r@example.com');
    ok($bob->has_pending, "multiple staged changes are pending together");
    is($bob->field('name'),  'robert',        "first pending change visible");
    is($bob->field('email'), 'r@example.com', "second pending change visible");
    is($bob->stored_field('name'),  'bob',             "stored name unchanged while pending");
    is($bob->stored_field('email'), 'bob@example.com', "stored email unchanged while pending");
    is(db_value(name  => $bob_pk), 'bob',             "db name unchanged while pending");
    is(db_value(email => $bob_pk), 'bob@example.com', "db email unchanged while pending");

    $bob->save;
    is(db_value(name  => $bob_pk), 'robert',        "both changes saved together (name)");
    is(db_value(email => $bob_pk), 'r@example.com', "both changes saved together (email)");

    $bob->update({name => 'bob', email => 'bob@example.com'});
};

subtest inflated_vs_raw_vs_stored => sub {
    is($bob->field('meta_json'),     {age => 42}, "field() inflates JSON to a ref");
    is($bob->raw_field('meta_json'), '{"age":42}', "raw_field() returns the raw db string");

    $bob->field(meta_json => {age => 43});
    is($bob->field('meta_json'),         {age => 43}, "pending inflated value");
    is($bob->pending_field('meta_json'), {age => 43}, "pending_field() shows pending value");
    is($bob->stored_field('meta_json'),  {age => 42}, "stored_field() inflates the original");
    is($bob->raw_stored_field('meta_json'), '{"age":42}', "raw_stored_field() shows original raw db value");



( run in 0.521 second using v1.01-cache-2.11-cpan-5b529ec07f3 )