Migrating Guide: Relationships System (v2.0.0-pre7)
This guide covers adopting the comprehensive relationships system introduced in v2.0.0-pre7.
Relationships System Overview
The v2.0.0-pre7 release introduces three powerful relationship types:
tracked_in- Multi-presence tracking with score encodingindexed_by- O(1) hash-based lookupsmember_of- Bidirectional membership with collision-free naming
Migration Steps
1. Enable Relationships Feature
Add the relationships feature to your models:
class Customer < Familia::Horreum
feature :relationships # Required for all relationship types
identifier_field :custid
field :custid, :name, :email
end
2. Choose Appropriate Relationship Types
For Tracking Collections (sorted sets):
class Customer < Familia::Horreum
feature :relationships
# Global tracking with score-based sorting
tracked_in :all_customers, type: :sorted_set, score: :created_at
# Scoped tracking
tracked_in :active_users, type: :sorted_set, score: :last_seen
end
For Fast Lookups (hash indexes):
class Customer < Familia::Horreum
feature :relationships
# Global email index for O(1) lookups
indexed_by :email, :email_lookup, target: :global
# Domain-specific indexes
indexed_by :account_id, :account_lookup, target: Domain
end
For Bidirectional Membership:
class Domain < Familia::Horreum
feature :relationships
# Belongs to customer's domains collection
participates_in Customer, :domains, type: :set
end
3. Implement Permission Systems
For access-controlled relationships:
class Document < Familia::Horreum
feature :relationships
include Familia::Features::Relationships::PermissionManagement
# Permission-aware tracking
tracked_in Customer, :documents, score: :created_at
:user_permissions
def
# Define permission levels (bit-encoded)
@permission_bits || 1 # Default: read-only
end
end
4. Update Queries
Before (manual db operations):
# Manual sorted set operations
redis.zadd("all_customers", customer.created_at, customer.custid)
customers = redis.zrange("all_customers", 0, -1)
After (relationship methods):
# Automatic method generation
Customer.add_to_all_customers(customer)
customers = Customer.all_customers.to_a
Relationship Method Patterns
tracked_in Methods
# Class methods generated:
Customer.add_to_all_customers(customer)
Customer.remove_from_all_customers(customer)
Customer.all_customers # Access sorted set directly
indexed_by Methods
# Class methods generated:
Customer.add_to_email_lookup(customer)
Customer.remove_from_email_lookup(customer)
Customer.email_lookup.get(email) # O(1) lookup
member_of Methods
# Instance methods generated:
domain.add_to_customer_domains(customer)
domain.remove_from_customer_domains(customer)
domain.in_customer_domains?(customer)
Permission System Migration
Basic Permission Encoding
# Permission levels (bit-encoded)
READ = 1 # 001
WRITE = 4 # 100
DELETE = 32 # 100000
ADMIN = 128 # 10000000
# Combine permissions
= READ | WRITE # Can read and write
= ADMIN # All permissions via hierarchy
Time-Based Permission Scores
# Encode timestamp with permission bits
= Familia.now.to_i
= READ | WRITE
score = Familia::Features::Relationships::ScoreEncoding.encode_score(, )
# Query by permission level
documents_with_write_access = customer.documents.accessible_items(
permissions: WRITE,
collection_key: customer.documents.key
)
Performance Considerations
Relationship Type Selection
Use indexed_by for:
- Unique field lookups (email, username, ID)
- Fields that need O(1) access
- Reference relationships
Use tracked_in for:
- Time-ordered collections
- Scored/ranked relationships
- Permission-based access control
Use member_of for:
- Simple membership tracking
- Bidirectional relationships
- UnsortedSet-based collections
Optimization Tips
Batch Operations:
# Instead of multiple individual operations
customers.each { |c| Customer.add_to_all_customers(c) }
# Use batch operations where available
Customer.all_customers.add_batch(customers.map(&:identifier),
customers.map(&:created_at))
Permission Queries:
# Efficient permission filtering
accessible_docs = document.accessible_items(
collection_key: customer.documents.key,
minimum_permissions: READ
)
Breaking Changes
Method Name Changes
- Relationship methods follow new naming patterns
- Previous manual db operations need updating
- Collection access methods standardized
Permission System
- New bit-encoded permission system
- Time-based scoring for temporal access
- Permission hierarchy implementation required
Next Steps
- Analyze Existing Relationships: Review current db operations for optimization opportunities
- Choose Relationship Types: Select appropriate types based on usage patterns
- Implement Permissions: Add access control where needed
- Update Queries: Replace manual operations with generated relationship methods
- Test Performance: Benchmark relationship operations under load
Resources
- Relationships Methods Guide - Complete method reference
- Relationships Guide - Implementation examples
- Performance Guide - Optimization strategies