module Sepia::Container

Overview

Module for objects that contain other Sepia objects.

The Container module enables objects to contain nested Serializable or Container objects. Containers serialize as directories on disk, with contained objects stored as files, subdirectories, or symlinks.

⚠️ WARNING: The Container API and on-disk format are subject to change. Data migrations will be required when upgrading Sepia versions.

Key Features

Directory Structure

container_id/
  ├── data.json           # Primitive properties (automatic)
  ├── simple_array/       # Array of primitives
  │   ├── 0000_value1
  │   └── 0001_value2
  ├── object_array/       # Array of Sepia objects
  │   ├── 0000 -> ../../ClassName/id1
  │   └── 0001 -> ../../ClassName/id2
  ├── nested_object/      # Single Sepia object
  │   └── 0000 -> ../../OtherClass/id
  └── complex_hash/       # Hash with mixed types
      ├── key1/value1     # Primitive value
      └── key2 -> ../../RefClass/id  # Sepia object reference

Example

class Project < Sepia::Object
  include Sepia::Container

  # Primitive properties - automatically serialized
  property name : String
  property created_at : Time
  property tags : Array(String)

  # Sepia object references - stored as symlinks
  owner : User?
  tasks : Array(Task)
  metadata : Hash(String, Document)?

  def initialize(@name = "")
    @created_at = Time.utc
    @tags = [] of String
    @tasks = [] of Task
  end
end

project = Project.new("My Project")
project.owner = user            # User object
project.tasks << task1 << task2 # Task objects
project.save                    # Creates directory structure

Defined in:

sepia/container.cr

Instance Method Summary

Instance Method Detail

def load_enumerable_of_containers(path : String, name : String, collection_type : T.class, item_type : U.class) forall T, U #

Loads an enumerable of containers from a directory of subdirectories.


[View source]
def load_enumerable_of_references(path : String, name : String, collection_type : T.class, item_type : U.class) forall T, U #

Loads an enumerable of serializable objects from a directory of symlinks.


[View source]
def load_hash_of_containers(path : String, name : String, collection_type : T.class, item_type : U.class) forall T, U #

Loads a hash of containers from a directory of subdirectories.


[View source]
def load_hash_of_references(path : String, name : String, collection_type : T.class, item_type : U.class) forall T, U #

Loads a hash of serializable objects from a directory of symlinks.


[View source]
def load_references(path : String) #

Loads all references (Serializable, Container, Enumerable of either) from the container's path.


[View source]
def log_activity(action : String, metadata) #

Logs an activity event for this container.

This method allows containers to log arbitrary activities that are not related to object persistence (save/delete operations). Activities are stored in the container's event log alongside other events.

Parameters

  • action : Description of the activity (e.g., "moved_lane", "edited")
  • metadata : Optional metadata for the activity (caller's responsibility for JSON serializability)

Example

board.log_activity("lane_created", {"lane_name" => "Review", "user" => "alice"})

# Simple version
board.log_activity("color_changed")

[View source]
def log_activity(action : String) #

Logs an activity event for this object (without metadata).

This method allows objects to log arbitrary activities that are not related to object persistence (save/delete operations). Activities are stored in the object's event log alongside other events.

Parameters

  • action : Description of the activity (e.g., "moved_lane", "edited")

Example

board.log_activity("color_changed")

[View source]
def restore_properties_from_json(json_data : String) #

Restore primitive properties from JSON without creating a new instance


[View source]
def save_references(path : String) #

Saves all references (Serializable, Container, Enumerable of either) to the container's path.


[View source]
def sepia_references : Enumerable(Sepia::Object) #

Returns all Sepia objects referenced by this container.

This method automatically inspects all instance variables and collects any Sepia objects, including those nested in Arrays, Hashes, and Sets. Used by the garbage collector to track object relationships.

Returns

An Enumerable containing all Sepia objects referenced by this container.

Example

class Team < Sepia::Object
  include Sepia::Container
  property members : Array(User)
  property lead : User?
  property projects : Hash(String, Project)

  def initialize
    @members = [] of User
    @projects = {} of String => Project
  end
end

team = Team.new
team.members << user1 << user2
team.lead = user3
team.projects["web"] = project1

refs = team.sepia_references
# refs contains [user1, user2, user3, project1]

[View source]
def to_filtered_json : String #

Serializes only primitive properties to JSON.

This method automatically filters out any Sepia object references, serializing only primitive types (String, Int32, Bool, Time, etc.) and collections of primitives. The resulting JSON is stored in the container's data.json file.

Returns

A JSON string containing only the primitive properties of the container.

Example

class UserProfile < Sepia::Object
  include Sepia::Container
  property name : String         # Included in JSON
  property age : Int32           # Included in JSON
  property friends : Array(User) # Excluded (Sepia objects)

  def initialize(@name = "", @age = 0)
    @friends = [] of User
  end
end

profile = UserProfile.new("Alice", 30)
json = profile.to_filtered_json
# json = {"name":"Alice","age":30,"friends":[]}

[View source]