<html>
<head>
  <title>OP Basics Cheat Sheet</title>
  <style>

a {
  color: #246;
}

body {
  background: #fff;
}

body, td {
  font-family: verdana, sans-serif;
  font-size: 9px;
}

h1, h2 {
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  background: #666;
  color: #ddd;
  padding: 4px;
  margin: 0px;
}

h3 {
  margin: 0px;
}

pre {
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  background: #666;
  color: #fff;
  padding: 4px;
  margin-bottom: 0px;
  font-family: monaco, courier new, monospace;
}

.item {
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  background: #ddd;
  padding: 4px;
  margin: 4px;
  margin-bottom: 8px;
}

  </style>
</head>
<body>

<h2 align="center" style="margin: 4px; background: #333; color: #fff">
  OP Basics Cheat Sheet
</h2>

<table border="0" cellspacing="0" cellpadding="0" width="100%">
  <tr>
    <td valign="top" width="20%">

<div class="item">
<h3><i>install</i> OP</h3>

<pre>
sudo perl -MCPAN -e 'install OP'
</pre>

<p>
This installs the latest stable version of OP.
</p>

<p>
You will also need <b>DBD::mysql</b>.
</p>
</div>

<div class="item">
<h3><i>create</i> a database</h3>

<p>
OP will create any necessary tables, but a DBA must create the
initial database, as well as run any required GRANT statements.
</p>

<pre>
mysql -u root -p
create database <i>yourapp</i>;
grant all on <i>yourapp</i>.* to op@localhost;
</pre>
</div>

<div class="item">
<h3><i>create</i> an object class</h3>

<p>
In file <i>YourApp/Example.pm</i>:
</p>

<pre>
use strict;
use warnings;

use OP qw| :all |;

create "<i>YourApp::Example</i>" => { };
</pre>
</div>


<div class="item">
<h3><i>assert</i> variable types</h3>

<p>Asserted types map to same-named database table columns.</p>

<pre>
create "<i>YourApp::Example</i>" => {
  favoriteNumber => OP::Int->assert(
    subtype(
      optional => true
    )
  ),

  favoriteColor  => OP::Str->assert(
    qw| red green blue |,
    subtype(
      optional => true
    )
  ),
};
</pre>

<p>
By default, instances have attributes: <b>id</b>, <b>name</b>,
<b>ctime</b>, and <b>mtime</b>.
</p>
</div>

    </td>
    <td valign="top" width="20%">

<div class="item">
<h3>make a <i>new</i> object</h3>

<pre>
use <i>YourApp::Example</i>;

my $class = "<i>YourApp::Example</i>";

my $example = $class->new(
  name => "HelloWorld"
);
</pre>
</div>

<div class="item">
<h3><i>save</i> an object</h3>

<pre>
$example->save;
</pre>
</div>

<div class="item">
<h3><i>load</i> an object</h3>

<p>
Load by GUID:
</p>

<pre>
my $example = $class->load($id);
</pre>

<p>
Load by Name:
</p>

<pre>
my $example = $class->loadByName("HelloWorld");
</pre>
</div>

<div class="item">
<h3><i>remove</i> an object</h3>

<pre>
$example->remove
</pre>
</div>

<div class="item">
<h3><i>query</i> the database</h3>

<p>Use <b>DBI</b> statement handles:</p>

<pre>
my $sth = $class->query(
  sprintf q| select id, name from %s |,
    $class->tableName
);

while ( my @row = $sth->fetchrow_array ) {
  print join ",", @row;
  print "\n";
};
</div>
    </td>

    <td valign="top" width="20%">

<div class="item">
<h3><i>set</i>, <i>get</i>, and <i>delete</i> an attribute</h3>

<p>Explicit:</p>

<pre>
$example->setFavoriteColor("blue");

my $color = $example->favoriteColor;

$example->deleteFavoriteColor;
</pre>

<p>Iterative:</p>

<pre>
$example->set("favoriteColor", "blue");

my $color = $example->get("favoriteColor");

$example->delete("favoriteColor");
</pre>
</div>

</pre>
</div>


<div class="item">
<h3>dump object <i>to json</i> or <i>yaml</i></h3>

<pre>
my $json = $object->toJson;

my $yaml = $object->toYaml;

#
# Prints YAML
#
$object->print;
</pre>
</div>

<div class="item">
<h3><i>load json</i> or <i>yaml</i> as object</h3>

<pre>
my $examp1 = $class->loadJson($json);

my $examp2 = $class->loadYaml($yaml);
</pre>
</div>

<div class="item">
<h3><i>assert</i> a foreign key constraint</h3>

<p>Use <b>OP::ExtID</b>:</p>

<pre>
create "YourApp::ThisClass" => {
  relatedId => OP::ExtID->assert(
    "YourApp::OtherClass"
  ),
};
</pre>
</div>

    </td>
    <td valign="top" width="20%">

<div class="item">
<h3>class <i>method</i></h3>

<p>Inline:</p>

<pre>
create "YourApp::Example" => {
  someMethod => sub {
    my $class = shift;

    # ...
  },

};
</pre>
</div>

<div class="item">
<h3>instance <i>method</i></h3>

<p>Inline:</p>

<pre>
create "YourApp::Example" => {
  someMethod => sub {
    my $self = shift;

    # ...
  },

};
</pre>
</div>

<div class="item">
<h3><i>collect</i> array elements</h3>

<pre>
my $collected = $array->collect( sub {
  my $item = shift;

  print "Working with element $item\n"

  return if $item == $foo; # Yield nothing

  break if $item == $bar;  # Stop collecting

  # Upstream $things, continue curr iteration:
  emit $thing1, [$thing2, ...];

  # Upstream $things, skip to next iteration:
  yield $thing1, [$thing2, ...];
} );
 
</pre>
</div>

    </td>
    <td valign="top" width="20%">

<div class="item">

<table width="100%">
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP.pm">OP</a></b></td>
    <td>Framework loader</td>
  </tr>

  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Array.pm">OP::Array</a></b></td>
    <td>List</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Bool.pm">OP::Bool</a></b></td>
    <td>Overloaded boolean</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/DateTime.pm">OP::DateTime</a></b></td>
    <td>Overloaded time object</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Domain.pm">OP::Domain</a></b></td>
    <td>Overloaded domain name</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Double.pm">OP::Double</a></b></td>
    <td>Overloaded double precision number</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/EmailAddr.pm">OP::EmailAddr</a></b></td>
    <td>Overloaded email address</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/ExtID.pm">OP::ExtID</a></b></td>
    <td>Overloaded foreign key</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Float.pm">OP::Float</a></b></td>
    <td>Overloaded floating point number</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Hash.pm">OP::Hash</a></b></td>
    <td>Hashtable</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/ID.pm">OP::ID</a></b></td>
    <td>Overloaded GUID</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/IPv4Addr.pm">OP::IPv4Addr</a></b></td>
    <td>Overloaded IPv4 address</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Int.pm">OP::Int</a></b></td>
    <td>Overloaded integer</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Name.pm">OP::Name</a></b></td>
    <td>A unique secondary key</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Num.pm">OP::Num</a></b></td>
    <td>Overloaded number</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Rule.pm">OP::Rule</a></b></td>
    <td>Regex</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/Str.pm">OP::Str</a></b></td>
    <td>Overloaded string</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/TimeSpan.pm">OP::TimeSpan</a></b></td>
    <td>Overloaded time range object</td>
  </tr>
  <tr>
    <td><b><a href="http://search.cpan.org/~aayars/OP/lib/OP/URI.pm">OP::URI</a></b></td>
    <td>Overloaded URI</td>
  </tr>
</table>

<p>OP classes may be instantiated (<i>$class->new(...)</i>), or declared
as inline attributes (<i>$class->assert(...)</i>).</p>

</div>
    </td>
  </tr>
</table>

</body>
</html>