NAME
    DBIx::MoCo - Light & Fast Model Component

SYNOPSIS
      # First, set up your db.
      package Blog::DataBase;
      use base qw(DBIx::MoCo::DataBase);

      __PACKAGE__->dsn('dbi:mysql:dbname=blog');
      __PACKAGE__->username('test');
      __PACKAGE__->password('test');

      1;

      # Second, create a base class for all models.
      package Blog::MoCo;
      use base qw 'DBIx::MoCo'; # Inherit DBIx::MoCo
      use Blog::DataBase;

      __PACKAGE__->db_object('Blog::DataBase');

      1;

      # Third, create your models.
      package Blog::User;
      use base qw 'Blog::MoCo';

      __PACKAGE__->table('user');
      __PACKAGE__->has_many(
          entries => 'Blog::Entry',
          { key => 'user_id' }
      );
      __PACKAGE__->has_many(
          bookmarks => 'Blog::Bookmark',
          { key => 'user_id' }
      );

      1;

      package Blog::Entry;
      use base qw 'Blog::MoCo';

      __PACKAGE__->table('entry');
      __PACKAGE__->has_a(
          user => 'Blog::User',
          { key => 'user_id' }
      );
      __PACKAGE__->has_many(
          bookmarks => 'Blog::Bookmark',
          { key => 'entry_id' }
      );

      1;

      package Blog::Bookmark;
      use base qw 'Blog::MoCo';

      __PACKAGE__->table('bookmark');
      __PACKAGE__->has_a(
          user => 'Blog::User',
          { key => 'user_id' }
      );
      __PACKAGE__->has_a(
          entry => 'Blog::Entry',
          { key => 'entry_id' }
      );

      1;

      # Now, You can use some methods same as in Class::DBI.
      # And, all objects are stored in cache automatically.
      my $user = Blog::User->retrieve(user_id => 123);
      print $user->name;
      $user->name('jkontan'); # update db immediately
      print $user->name; # jkontan

      my $user2 = Blog::User->retrieve(user_id => 123);
      # $user is same as $user2

      # You can easily get has_many objects array.
      my $entries = $user->entries;
      my $entries2 = $user->entries;
      # $entries is same reference as $entries2
      my $entry = $entries->first; # isa Blog::Entry
      print $entry->title; # you can use methods in Entry class.

      Blog::Entry->create(
        user_id => 123,
        title => 'new entry!',
      );
      # $user->entries will be flushed automatically.
      my $entries3 = $user->entries;
      # $entries3 isnt $entries

      print ($entries->last eq $entries2->last); # 1
      print ($entries->last eq $entries3->last); # 1
      # same instance

      # You can delay update/create query to database using session.
      DBIx::MoCo->start_session;
      $user->name('jkondo'); # not saved now. changed in cache.
      print $user->name; # 'jkondo'
      $user->save; # update db
      print Blog::User->retrieve(123)->name; # 'jkondo'

      # Or, update queries will be thrown automatically after ending session.
      $user->name('jkontan');
      DBIx::MoCo->end_session;
      print Blog::User->retrieve(123)->name; # 'jkontan'

DESCRIPTION
    Light & Fast Model Component

CLASS METHODS
    Here are common class methods of DBIx::MoCo.

    has_a
        Defines has_a relationship between 2 models.

    has_many
        Defines has_many relationship between 2 models.

    retrieve_keys
        Defines keys for retrieving by retrieve_all etc. If there aren't any
        unique keys in your table, please specify these keys.

          package Blog::Bookmark;

          __PACKAGE__->retrieve_keys(['user_id', 'entry_id']);
          # When user can add multiple bookmarks onto same entry.

    start_session
    end_session
    is_in_session
    cache_status
        Returns cache status hash reference. cache_status provides
        retrieve_count, retrieve_cache_count, retrieved_oids
        retrieve_all_count, has_many_count, has_many_cache_count,

    cache
        Set or get cache.

    flush_cache
        Remove given cache value.

    schema
        Returns DBIx::MoCo::Schema object reference related with your model
        class.

    primary_keys
    unique_keys
    columns
    retrieve
    retrieve_or_create
    retrieve_all
    retrieve_all_id_hash
    create
    delete_all
    count
    search
    retrieve_by_column(_and_column2)
    retrieve_by_column(_and_column2)_or_create
    retrieve_by_column_or_column2
    column_as_something
        Inflate column value by using DBIx::MoCo::Column::* plugins. If you
        set up your plugin like this,

          package DBIx::MoCo::Column::MyColumn;

          sub MyColumn {
            my $self = shift;
            return "My Column $$self";
          }

          1;

        Then, you can use column_as_MyColumn method

          my $o = MyObject->retrieve(..);
          print $o->name; # "jkondo"
          print $o->name_as_MyColumn; # "My Column jkondo";

        You can also inflate your column value by other classes.

    has_a, has_many auto generated methods
        If you define has_a, has_many relationships,

          package Blog::Entry;
          use base qw 'Blog::MoCo';

          __PACKAGE__->table('entry');
          __PACKAGE__->has_a(
              user => 'Blog::User',
              { key => 'user_id' }
          );
          __PACKAGE__->has_many(
              bookmarks => 'Blog::Bookmark',
              { key => 'entry_id' }
          );

        You can use those keys as methods.

          my $e = Blog::Entry->retrieve(..);
          print $e->user; # isa Blog::User
          print $e->bookmarks; # isa ARRAY of Blog::Bookmark

CLASS OR INSTANCE METHODS
    Here are common class or instance methods of DBIx::MoCo.

    object_id
    delete

INSTANCE METHODS
    Here are common instance methods of DBIx::MoCo.

    flush
        Delete attribute from given attr. name.

    param
        Set or get attribute from given attr. name.

    set Set attribute which is not related with DB schema or set temporary.

    has_primary_keys
    save
        Saves changed columns in session.

    object_ids
        Returns all possible object-ids.

FORM VALIDATION
    You can validate user parameters using moco's schema. For example you
    can define your validation profile using param like this,

      package Blog::User;

      __PACKAGE__->schema->param([
        name => ['NOT_BLANK', 'ASCII', ['DBIC_UNIQUE', 'Blog::User', 'name']],
        mail => ['NOT_BLANK', 'EMAIL_LOOSE'],
      ]);

    And then,

      # In your scripts
      sub validate {
        my $self = shift;
        my $q = $self->query;
        my $prof = Blog::User->schema->param('validation');
        my $result = FormValidator::Simple->check($q => $prof);
        # handle errors ...
      }

SEE ALSO
    SQL::Abstract, Class::DBI, Cache,

AUTHOR
    Junya Kondo, <http://use.perl.org/~jkondo/>, Naoya Ito,
    <naoya@hatena.ne.jp>

COPYRIGHT AND LICENSE
    Copyright (C) Hatena Inc. All Rights Reserved.

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