NAME

OP::Class - Root-level "Class" class

VERSION

$Id: //depotit/tools/source/snitchd-0.20/lib/OP/Class.pm#9 $

SYNOPSIS

Class Allocation

#
# File: OP/Example.pm
#

use OP qw| create true false |;

create "OP::Example" => {
  #
  # This is an empty class prototype
  #
};

Class Consumer

#
# File: testscript.pl
#

use strict;
use warnings;

use OP::Example;

my $exa = OP::Example->new();

$exa->setName("My First OP Object");

$exa->save("This is a checkin comment");

say "Saved object:";

$exa->print();

DESCRIPTION

OP::Class is the root-level parent class in OP, and also provides the class prototyping function create().

METHODS

Public Class Methods

  • get(OP::Class $class: Str $key)

    Get the named class variable

    my $class = "OP::Example";
    
    my $scalar = $class->get($key);
    
    my @array = $class->get($key);
    
    my %hash = $class->get($key);
  • set(OP::Class $class: Str $key, *@value)

    Set the named class variable to the received value

    my $class = "OP::Example";
    
    $class->set($key, $scalar);
    
    $class->set($key, @array);
    
    $class->set($key, %hash);
  • pretty(OP::Class $class: Str $key)

    Transform camelCase to Not Camel Case

    my $class = "OP::Example";
    
    my $uglyStr = "betterGetThatLookedAt";
    
    my $prettyStr = $class->pretty($uglyStr);
  • members(OP::Class $class:)

    Class introspection method.

    Return an array ref of all messages supported by this class.

    Does not include messages from superclasses.

    my $members = OP::Example->members();
  • membersHash(OP::Class $class:)

    Class introspection method.

    Return a hash ref of all messages supported by this class.

    Does not include messages from superclasses.

    my $membersHash = OP::Example->membersHash();

Private Class Methods

  • init(OP::Class $class:)

    Abstract callback method invoked immediately after a new class is allocated via create().

    Override in subclass with additional logic, if necessary.

  • __checkVarName(OP::Class $class: Str $varName)

    Checks the "safeness" of a class variable name before eval'ing it.

PROTOTYPE COMPONENTS

Class (Package) Name

The name of the class being created is the first argument sent to create().

use OP qw| create |;

#
# The class name will be "OP::Example":
#
create "OP::Example" => {

};

Class Prototype

A class prototype is a hash describing all fundamental characteristics of an object class. It's the second argument sent to create().

create "OP::Example" => {
  #
  # This is an empty prototype (perfectly valid)
  #
};

Instance Variables

Instance variables are declared with the assert class method:

create "YourApp::Example" => {
  favoriteNumber => OP::Int->assert(
    ::optional
  ),

  favoriteColor  => OP::Str->assert(
    qw| red green blue |,
    ::optional
  ),
};

Instance Methods

Instance methods are declared as keys in the class prototype. The name of the method is the key, and its value in the prototype is a Perl 5 sub{}.

create "OP::Example" => {
  #
  # Add a public instance method, $self->handleFoo()
  #
  handleFoo => sub {
    my $self = shift;

    printf 'The value of foo is %s', $self->foo();
    print "\n";

    return true;
  }
}

my $exa = OP::Example->new();

$exa->setFoo("Bar");

$exa->handleFoo();

#
# Expected output:
#
# The value of foo is Bar
#

The OP convention for private or protected instance methods is to prefix them with a single underscore.

create "OP::Example" => {
  #
  # private instance method
  #
  _handleFoo => sub {
    my $self = shift;

    say "The value of foo is $self->{foo}";
  }
};

Class Variables

Class variables are declared as keys in the class prototype. They should be prepended with double underscores (__). The value in the prototype is the literal value to be used for the class variable.

use OP qw| create true false |;

create "OP::Example" => {
  #
  # Override a few class variables
  #
  __useYaml => false,
  __dbiType => OP::DBIType::MySQL
};

OP class variables are just Perl package variables, scoped in a list using our.

package OP::Example;

use OP qw| true false |;

use base qw| OP::Node |;

our @__useYaml = false;
our @__dbiType = OP::DBIType::MySQL;

true;

Class Methods

Class methods are declared in the same manner as instance methods. The only difference is that the class will be the receiver.

create "OP::Example" => {
  #
  # Add a public class method
  #
  loadXml => sub {
    my $class = shift;
    my $xml = shift;

    # ...
  }
};

The OP convention for private or protected class methods is to prefix them with double underscores.

create "OP::Example" => {
  #
  # Override a private class method
  #
  __basePath => sub {
    my $class = shift;

    return join('/', '/tmp', $class);
  }
};

Inheritance

By default, classes created with create() inherit from OP::Node. To override this, include a __BASE__ attribute, specifying the parent class name.

create "OP::Example" => {
  #
  # Override parent class
  #
  __BASE__ => "Acme::CustomClass"
};

OPTIONAL EXPORTS

Constants

  • true, false

    Constants provided by OP::Enum::Bool

    use OP qw| true false |;

Functions

  • create(Str $class: Hash $prototype)

    use OP qw| create |;

    Allocate a new OP-derived class.

    Objects instantiated from classes allocated with create() have built-in runtime assertions-- simple but powerful rules in the class prototype which define runtime and schema attributes. See the OP::Type module for more about assertions.

    OP classes are regular old Perl packages. create() is just a wrapper to the package keyword, with some shortcuts thrown in.

    use OP qw| create true false |;
    
    create "OP::Example" => {
      __someClassVar => true,
    
      someInstanceVar => OP::Str->assert(),
    
      anotherInstanceVar => OP::Str->assert(),
    
      publicInstanceMethod => sub {
        my $self = shift;
    
        # ...
      },
    
      _privateInstanceMethod => sub {
        my $self = shift;
    
        # ...
      },
    
      publicClassMethod => sub {
        my $class = shift;
    
        # ...
      },
    
      __privateClassMethod => sub {
        my $class = shift;
    
        # ...
      },
    };

DIAGNOSTICS

XXX TODO Figure out what to put in this section.

CONFIGURATION AND ENVIRONMENT

OP looks for the .oprc configuration file under the location specified by $OP_HOME. See OP::Constants for details.

OP under mod_perl/mod_perl2

OP classes should be precompiled under mod_perl by referencing them in the Apache instance's startup.pl script. OP_HOME must be set in a BEGIN block.

#
# File: startup.pl
#
BEGIN {
  $ENV{OP_HOME} = '/home/user/op'; # Directory with the .oprc
}

#
# Load any OP-derived packages at startup:
#
use MyApp::Component;
use MyApp::OtherComponent;

1;

OP under HTML::Mason

OP classes should be preloaded by startup.pl, as in the above example.

If (and only if) you are not using a startup.pl: Mason loads packages outside the context of package main, but OP must currently be bootstrapped from package main, so one must explicitly drop back into main before consuming OP-derived classes. Do this in a do block.

<%init>

  do {
    package main;

    use MyApp::Component;
  }

</%init>
<%perl>

  $m->print( MyApp::Component->sayHello() );

</%perl>

It is highly recommended that startup.pl be used in production environments, so the initial requests to the webserver are not delayed by the lengthy source filtering and compilation steps.

#
# File: httpd.conf
#
PerlModule HTML::Mason::ApacheHandler
PerlRequire /opt/op/bin/startup.pl

<LocationMatch "/.*\.html$">
  SetHandler perl-script

  PerlHandler HTML::Mason::ApacheHandler
</LocationMatch>

DEPENDENCIES

OP's dependencies are numerous, and subject to change while the API is ironed out. See the Makefile.PL which accompanied this distribution for a current list of prerequisites.

INCOMPATIBILITIES

Probably.

BUGS AND LIMITATIONS

Likely.

Test suite is currently incomplete.

SEE ALSO

OP::Type, OP::Subtype

This file is part of OP.