NAME

Devel::Ladybug::ExtID - Overloaded object class for foreign key constraints.

Extends Devel::Ladybug::Str.

SYNOPSIS

use Devel::Ladybug qw| :all |;

create "YourApp::Example" => {
  categoryId => Devel::Ladybug::ExtID->assert(
    "YourApp::Category"
  ),

};

PUBLIC CLASS METHODS

  • $class->assert([$query], @rules)

    ExtID assertions are like pointers defining relationships with other classes, or within a class to define parent/child hierarchy.

    Attributes asserted as ExtID must match an id in the specified class's database table.

    ExtID may be wrapped in an Array assertion for handling one-to-many relationships, at a small performance cost.

    If using MySQL, ExtID also enforces database-level foreign key constraints. In addition to enforcing allowed values on the database level, this will incur a CASCADE operation on DELETE and UPDATE events (meaning if a parent is deleted or updated, the corresponding child rows will be deleted or updated as well; always use parent id in a child object, rather than child id in a parent object).

    The following example illustrates self-referencing and externally referencing attributes with ExtID, using the "Folder" and "Document" desktop paradigm. Each saved object becomes a row in a database table.

    Create a folder class for documents and other folders:

    #
    # File: ExampleFolder.pm
    #
    
    use Devel::Ladybug qw| :all |;
    
    create "YourApp::Example::Folder" => {
      #
      # Folders can go in other folders:
      #
      parentId => Devel::Ladybug::ExtID->assert(
        "YourApp::Example::Folder",
        subtype(
          optional => 1
        )
      ),
    
      ...
    };

    A document class. Documents refer to their parent folder:

    #
    # File: ExampleTextDocument.pm
    #
    
    use Devel::Ladybug qw| :all |;
    use YourApp::Example::Folder;
    
    create "YourApp::Example::TextDocument" => {
      #
      # This doc's location in the folder hierarchy
      #
      folderId => Devel::Ladybug::ExtID->assert("YourApp::Example::Folder"),
    
      #
      # Textual content of the document
      #
      content  => Devel::Ladybug::Str->assert(
        subtype(
          columnType => "TEXT"
        )
      ),
    
      # ...
    };

    Caller example which populates some test folders and docs:

    #!/bin/env perl
    #
    # File: somecaller.pl
    #
    
    use strict;
    use warnings;
    
    use YourApp::Example::Folder;
    use YourApp::Example::TextDocument;
    
    sub main {
      #
      # A parent folder named "General"
      #
      my $folder = YourApp::Example::Folder->spawn("General");
      $folder->save();
    
      #
      # A child folder named "Specific"
      #
      my $subfolder = YourApp::Example::Folder->spawn("Specific");
      $subfolder->setFolderId( $folder->id() );
      $subfolder->save();
    
      #
      # Put a test document "README" in the parent folder:
      #
      my $readme = YourApp::Example::TextDocument->spawn("README");
      $readme->setFolderId( $folder->id() );
      $readme->setContent("Lorem Ipsum Foo! Bla bla bla...");
      $readme->save();
    
      #
      # Put a "Test Text Doc" doc in the sub-folder:
      #
      my $doc = YourApp::Example::TextDocument->spawn("Test Text Doc");
      $doc->setFolderId( $subfolder->id() );
      $doc->setContent("Lorem Ipsum Foo! Bla bla bla...");
      $doc->save();
    }
    
    main();

    If a string is specified as a second argument to ExtID, it will be used as a SQL query, which selects a subset of Ids used as allowed values at runtime. If this query is not given, a flat, immutable list of Ids will be plugged in for allowed values at compile time.

    create "YourApp::Example::" => {
      userId => Devel::Ladybug::ExtID->assert(
        "YourApp::Example::::User",
        "select id from example_user where foo = 1"
      ),
    
      # ...
    };

SEE ALSO

This file is part of Devel::Ladybug.