Skip to content
moellep edited this page Nov 5, 2014 · 15 revisions

In this step, we'll add the PropertyModel and its database schema, along with the MyStatusCode enum type.

My-Status Classes (Click for larger view)

  • First we define the Model.MyStatus as a new file Model/MyStatus.pm. The MyStatus model derives from Model.RealmBase which provides support for automatically updating the user_id and modified_date_time fields.
package NewProject::Model::MyStatus;
use strict;
use Bivio::Base 'Model.RealmBase';

sub execute_load_or_create_for_auth_user {
    my($proto, $req) = @_;
    # To be called from a Task - load the current model for the Realm/User
    # or create one with default values.
    $proto->new($req)->load_or_create_for_auth_user;
    return;
}

sub internal_initialize {
    my($self) = @_;
    return $self->merge_initialize_info($self->SUPER::internal_initialize, {
        version => 1,
        table_name => 'my_status_t',
        columns => {
            realm_id => ['RealmOwner.realm_id', 'PRIMARY_KEY'],
            user_id => ['User.user_id', 'PRIMARY_KEY'],
            status_code => ['MyStatusCode', 'NOT_NULL'],
            status_comment => ['Text', 'NONE'],
            modified_date_time => ['DateTime', 'NOT_NULL'],
        },
    });
}

sub load_or_create_for_auth_user {
    my($self) = @_;
    if ($self->unsafe_load({
        user_id => $self->req('auth_user_id'),
    })) {
        return $self;
    }
    return $self->create({
        status_code => b_use('Type.MyStatusCode')->UNKNOWN,
    });
}

1;
  • Next we add the database schema definition to the files/npx/ddl/np-tables.sql
CREATE TABLE my_status_t (
  realm_id NUMERIC(18) NOT NULL,
  user_id NUMERIC(18) NOT NULL,
  status_code NUMERIC(2) NOT NULL,
  status_comment VARCHAR(500),
  modified_date_time DATE NOT NULL,
  CONSTRAINT my_status_t1 PRIMARY KEY(realm_id, user_id)
)
/
  • And database constraints, files/npx/ddl/np-constraints.sql
ALTER TABLE my_status_t
  ADD CONSTRAINT my_status_t2
  FOREIGN KEY (realm_id)
  REFERENCES realm_owner_t(realm_id)
/
CREATE INDEX my_status_t3 ON my_status_t (
  realm_id
)
/
ALTER TABLE my_status_t
  ADD CONSTRAINT my_status_t4
  FOREIGN KEY (user_id)
  REFERENCES user_t(user_id)
/
CREATE INDEX my_status_t5 ON my_status_t (
  user_id
)
/
  • Then we create the new enum Type.MyStatusCode, creating the file Type/MyStatusCode.pm
package NewProject::Type::MyStatusCode;
use strict;
use Bivio::Base 'Type.Enum';

__PACKAGE__->compile([
    UNKNOWN => 0,
    AWAY => 1,
    BUSY => 2,
    IDLE => 3,
    OFFLINE => 4,
]);

1;
  • Now we can recreate the database schema to include our new Property model by running:
$ bivio SQL -force create_test_db
  • Finally, create a bunit test which tests the create/update methods on our new PropertyModel. Create a new file Model/t/MyStatus.bunit
PropertyModel();
req()->set_realm_and_user('site', 'adm');
[
    # remove the model if it exists
    delete => [
        [{
            user_id => req('auth_user_id'),
            realm_id => req('auth_id'),
        }] => not_die(),
    ],
    # create a new model, verify defaults
    load_or_create_for_auth_user => [
        [] => [{
            'Model.MyStatus' => {
                status_code => Type_MyStatusCode()->UNKNOWN,
                status_comment => undef,
            },
        }],
    ],
    # update the MyStatus model and verify the change
    update => [
        [{
            status_comment => 'At lunch',
            status_code => Type_MyStatusCode()->BUSY,
        }] => [{
            'Model.MyStatus' => {
                status_code => Type_MyStatusCode()->BUSY,
                status_comment => 'At lunch',
            },
        }],
    ],
    # verify load_or_create() returns the same values
    load_or_create_for_auth_user => [
        [] => [{
            'Model.MyStatus' => {
                status_code => Type_MyStatusCode()->BUSY,
                status_comment => 'At lunch',
            },
        }],
    ],
    # all changes are rolled back at the end of the bunit
];
  • Run the test from the command line:
$ bivio Test unit MyStatus.bunit
      MyStatus.bunit: PASSED
Output:
  1..3
  ok 1
  ok 2
  ok 3
  ok 4
  All (4) tests PASSED
All (1) tests PASSED
Clone this wiki locally