Module: Familia::Features::Relationships::Participation

Defined in:
lib/familia/features/relationships/participation.rb,
lib/familia/features/relationships/participation/through_model_operations.rb

Overview

Participation module for bidirectional business relationships using Valkey/Redis collections. Provides semantic, scored relationships with automatic reverse tracking.

Unlike Indexing (which is for attribute lookups), Participation manages relationships where membership has meaning, scores have semantic value, and bidirectional tracking is essential

=== Architecture Overview === This module is organized into clear, separate concerns:

  1. CollectionOperations: Shared helpers for all collection manipulation
  2. ParticipantMethods: Methods added to the class calling participates_in
  3. TargetMethods: Methods added to the target class specified in participates_in

This separation makes it crystal clear what methods are added to which class.

Key Differences from Indexing:

  • Participation: Bidirectional relationships with semantic scores
  • Indexing: Unidirectional lookups without relationship semantics
  • Participation: Collection name in key (customer:123:domains)
  • Indexing: Field value in key (company:123:dept_index:engineering)

When to Use Participation:

  • Modeling business relationships (Customer owns Domains)
  • Scores have meaning (priority, permissions, join_date)
  • Need bidirectional tracking ("what collections does this belong to?")
  • Relationship lifecycle matters (cascade cleanup, reverse tracking)

Examples:

Basic participation with temporal scoring

class Domain < Familia::Horreum
  feature :relationships
  field :created_at
  participates_in Customer, :domains, score: :created_at
end

# TARGET (Customer) gets collection management:
customer.domains                    # → Familia::SortedSet (by created_at)
customer.add_domain(domain)         # → adds with created_at score
customer.remove_domain(domain)      # → removes + cleans reverse index
customer.add_domains([d1, d2, d3])  # → efficient bulk addition

# PARTICIPANT (Domain) gets membership methods:
domain.in_customer_domains?(customer)              # → true/false
domain.add_to_customer_domains(customer)           # → self-addition
domain.remove_from_customer_domains(customer)      # → self-removal
domain.participations                              # → reverse index tracking

Class-level participation (all instances auto-tracked)

class User < Familia::Horreum
  feature :relationships
  field :created_at
  class_participates_in :all_users, score: :created_at
end

User.all_users              # → Familia::SortedSet (class-level)
user.in_class_all_users?    # → true if auto-added
user.add_to_class_all_users # → explicit addition

Semantic scores with permission encoding

class Domain < Familia::Horreum
  feature :relationships
  field :created_at
  field :permission_bits

  participates_in Customer, :domains,
    score: -> { permission_encode(created_at, permission_bits) }
end

customer.domains_with_permission(:read)  # → filtered by score

Defined Under Namespace

Modules: ModelClassMethods, ModelInstanceMethods, ThroughModelOperations

Class Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Hook called when module is included in a class.

Extends the host class with ModelClassMethods for relationship definitions and includes ModelInstanceMethods for instance-level operations.

Parameters:

  • base (Class)

    The class including this module



94
95
96
97
98
# File 'lib/familia/features/relationships/participation.rb', line 94

def self.included(base)
  base.extend ModelClassMethods
  base.include ModelInstanceMethods
  super
end