The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

OP::Type - Type definitions for OP::Object subclass instances

DESCRIPTION

A Type describes the parameters which an OP::Object instance variable and/or database table column must conform to, and does so in a detailed and compact form. The OP::Type class also provides methods for strict runtime testing and enforcement of asserted values.

If a caller tries to do something contrary to a Type, OP will throw an exception, which causes an exit unless caught using eval/$@ or try/catch (see Error).

Dynamic Subclasses

The "built-in" subclasses derived from OP::Type and OP::Subtype are auto-generated, and have no physical modules.

Each concrete object class in OP provides access to its respective Type subclass, via the __assertClass() and __assert() class methods. For example, OP::Str provides access to the dynamic class OP::Type::Str; OP::Hash does so for OP::Type::Hash; etc.

Types may be modified by Subtypes (e.g. ::optional()). See OP::Subtype for more details and a list of these rule types. Subtype subclasses are allocated from the definitions found in the %OP::Type::RULES package variable.

SYNOPSIS

Using "package"

When using package, instance variables are asserted using member().

  package OP::Example;

  use OP;

  use base qw| OP::Node |;

  #
  # Instance variable "foo" will contain optional string data:
  #
  member foo => OP::Str->assert( ::optional() );

  ...

  true;

Using "create"

If creating classes using create(), instance variables are asserted in the prototype as inline keys.

  use OP;

  create "OP::Example" => {
    #
    # Instance variable "foo" will contain optional string data:
    #
    foo => OP::Str->assert( ::optional() ),

    ...
  };

More examples can be found in the OP::Class and OP::Subtype modules, and in the documentation for specific object classes.

The remainder of this doc contains information which is generally only useful if hacking on core OP internals.

TEST SUBS

These subs are defined as package constants, and are used internally by OP. These subs are not for general usage, but for coding OP internals.

Each returns a CODE block which may be used to validate data types.

When executed, the test subs throw an OP::AssertFailed exception on validation failure, and return true on success.

  • insist(Any $value, Code $test);

    Runs the received value against a test sub.

      #
      # OP will agree, $str is string-like.
      #
      my $str = "Hello";
    
      insist($str, OP::Type::isStr);
    
      #
      # This will throw an exception:
      #
      my $notStr = { };
    
      insist($notStr, OP::Type::isStr);
  • isStr(Str $value)

    Returns a CODE ref which tests the received value for string-ness.

  • isFloat(Num $value)

    Returns a CODE ref which tests the received value for float-ness.

  • isInt(Num $value)

    Returns a CODE ref which tests the received value for int-ness.

  • isArray(Array $value)

    Returns a CODE ref which tests the received value for array-ness.

  • isBool(Bool $value)

    Returns a CODE ref which tests the received value for bool-ness.

  • isCode(Code $code)

    Returns a CODE ref which tests the received value for CODE-ness.

  • isHash(Hash $value)

    Returns a CODE ref which tests the received value for hash-ness.

  • isIO(IO $io)

    Returns a CODE ref which tests the received value for IO-ness.

  • isRef(Ref $ref)

    Returns a CODE ref which tests the received value for ref-ness.

  • isRule(Rule $rule)

    Returns a CODE ref which tests the received value for regex-ness.

  • isScalar(Str $scalar)

    Returns a CODE ref which tests the received value for scalar-ness.

FUNCTIONS

OP::Type's exported functions are used to bootstrap OP::Class subclasses.

  • member($key,$type)

    Instance variable assertion function.

    member() is only needed when using package. If using create(), assertions are just inline keys in the prototype, and this function should not be used directly.

    The member() function defines allowed instance variables for any objects of a class, and is exported by the OP::Class module for this purpose. Assertions restrict the attributes and values which objects of a class may have. The attributes asserted in a class translate to same-named database table columns.

    If no class members are asserted, objects will receive "free-form" getters and setters. These "schema-less" instances may be saved to disk, but not to a database.

      package OP::Example;
    
      use OP;
    
      use base "OP::Node";
    
      our @__someClassVar = true;
    
      member someInstanceVar => OP::Str->assert();
    
      member anotherInstanceVar => OP::Str->assert();
    
      method publicInstanceMethod() {
        # Code here, $self will be set for you.
      }
    
      method _privateInstanceMethod() {
        # Code here, $self will be set for you.
      }
    
      method publicClassMethod(OP::Class $class:) {
        # Code here, $class will be set for you.
      }
    
      method __privateClassMethod(OP::Class $class:) {
        # Code here, $class will be set for you.
      }
    
      true;

PUBLIC CLASS METHODS

These methods are used internally by OP at a low level, and normally won't be accessed directly.

If creating a new Type subclass from scratch, its constructors and methods would need to implement this interface.

  • $class->new(%args)

    Instantiate a new OP::Type object.

    Consumed args are as follows:

      my $type = OP::Type::MyType->new(
        code       => ..., # CODE ref to test with
        allowed    => ..., # ARRAY ref of allowed vals
        default    => ..., # Literal default value
        columnType => ..., # Override column type string
        sqlValue   => ..., # Override SQL insert value
        unique     => ..., # true|false
        optional   => ..., # true|false
        serial     => ..., # true|false
        min        => ..., # min numeric value
        max        => ..., # max numeric value
        size       => ..., # fixed length or scalar size
        minSize    => ..., # min length or scalar size
        maxSize    => ..., # max length or scalar size
        regex      => ..., # optional regex which value must match
        memberType => ..., # Sub-assertion for arrays
        memberClass  => ..., # Name of inline or external class
        uom        => ..., # String label for human reference
        descript   => ..., # Human-readable description
        example    => ..., # An example value for human reference
        onDelete   => ..., # MySQL foreign constraint reference option
        onUpdate   => ..., # MySQL foreign constraint reference option
        
      );

READ-ONLY ATTRIBUTES

Although these are public-ish, there normally should not be a need to access them directly.

  • $type->allowed()

    Returns the array of allowed values for this asserted attribute.

    XXX TODO This would be much faster as a hash table keyed on value

  • $type->code()

    Returns the CODE ref used to test this attribute's value for correctness. The code ref is a sub{ } block which takes the value as an argument, and returns a true or false value.

  • $type->memberType()

    Used for Arrays only. Returns a "sub-assertion" (another OP::Type object) which is unrolled for array elements.

  • $type->memberClass()

    Used for OP::ExtID assertions only. Returns the name of the class which this attribute is a pointer to.

  • $type->externalClass()

    Convenience wrapper for memberClass, but also works for Arrays of ExtIDs. One-to-one foreign keys are asserted as ExtID, but one-to-many keys are an ExtID assertion wrapped in an Array assertion. This means a lot of double-checking in code later, so this method exists to handle both cases without fuss.

    Used for OP::ExtID assertions (one-to-one) and OP::Array assertions encapsulating an ExtID, to return the name of the class which the current attribute is a pointer to.

  • $type->objectClass()

    Returns the concrete object class which this type is for.

PUBLIC INSTANCE METHODS

  • $self->class()

    Object wrapper for Perl's built-in ref() function

  • $type->test($key, $value)

    Send the received value to the code reference returned by $type->code(). Warns and returns a false value on test failure, otherwise returns true.

    $key is included so the caller may know what the warning was for!

    XXX TODO The individual tests need moved out of this monolithic sub, and into the assertion code tests. Will make things cleaner and faster.

SEE ALSO

OP::Class, OP::Subtype

This file is part of OP.

REVISION

$Id: $

1 POD Error

The following errors were encountered while parsing the POD:

Around line 162:

You forgot a '=back' before '=head1'