require 'familia'
Familia.configure do |config|
config.uri = 'redis://localhost:6379/'
end
puts '=== Familia Relationships Basic Example ==='
puts
class Customer < Familia::Horreum
logical_database 15 feature :relationships
identifier_field :custid
field :custid
field :name
field :email
field :plan
set :domains list :projects sorted_set :activity
class_indexed_by :email, :email_lookup class_indexed_by :plan, :plan_lookup
class_tracked_in :all_customers, score: :created_at end
class Domain < Familia::Horreum
logical_database 15 feature :relationships
identifier_field :domain_id
field :domain_id
field :name
field :dns_zone
field :status
member_of Customer, :domains
class_tracked_in :active_domains,
score: -> { status == 'active' ? Time.now.to_i : 0 }
end
class Project < Familia::Horreum
logical_database 15 feature :relationships
identifier_field :project_id
field :project_id
field :name
field :priority
member_of Customer, :projects, type: :list
end
puts '=== 1. Basic Object Creation ==='
customer = Customer.new(
name: 'Acme Corporation',
email: 'admin@acme.com',
plan: 'enterprise'
)
domain1 = Domain.new(
name: 'acme.com',
dns_zone: 'acme.com.',
status: 'active'
)
domain2 = Domain.new(
name: 'staging.acme.com',
dns_zone: 'staging.acme.com.',
status: 'active'
)
project = Project.new(
name: 'Website Redesign',
priority: 'high'
)
puts "✓ Created customer: #{customer.name} (#{customer.custid})"
puts "✓ Created domains: #{domain1.name}, #{domain2.name}"
puts "✓ Created project: #{project.name}"
puts
puts '=== 2. Establishing Relationships ==='
customer.save puts '✓ Customer automatically added to indexes and tracking on save'
customer.domains << domain1 customer.domains << domain2 customer.projects << project
puts '✓ Established domain ownership relationships using << operator'
puts '✓ Established project ownership relationships using << operator'
domain1.save domain2.save puts '✓ Domains automatically added to status tracking on save'
puts
puts '=== 3. Querying Relationships ==='
record = Customer.get_by_email('admin@acme.com')
puts "Email lookup: #{record&.custid || 'not found'}"
Customer.get_by_plan('enterprise')
results = Customer.find_by_email('admin@acme.com')
puts "Email lookup: #{results&.size} found"
results = Customer.find_by_plan('enterprise')
puts "Enterprise lookup: #{results&.size} found"
puts
puts "\nDomain membership checks:"
puts " #{domain1.name} belongs to customer? #{domain1.in_customer_domains?(customer)}"
puts " #{domain2.name} belongs to customer? #{domain2.in_customer_domains?(customer)}"
puts "\nCustomer collections:"
puts " Customer has #{customer.domains.size} domains"
puts " Customer has #{customer.projects.size} projects"
puts " Domain IDs: #{customer.domains.members}"
puts " Project IDs: #{customer.projects.members}"
all_customers_count = Customer.values.size
puts "\nClass-level tracking:"
puts " Total customers in system: #{all_customers_count}"
active_domains_count = Domain.active_domains.size
puts " Active domains in system: #{active_domains_count}"
puts
puts '=== 4. Range Queries ==='
yesterday = (Time.now - (24 * 3600)).to_i recent_customers = Customer.values.rangebyscore(yesterday, '+inf')
puts "Recent customers (last 24h): #{recent_customers.size}"
active_domain_scores = Domain.active_domains.rangebyscore(1, '+inf', with_scores: true)
puts 'Active domains with timestamps:'
active_domain_scores.each_slice(2) do |domain_id, timestamp|
puts " #{domain_id}: active since #{Time.at(timestamp.to_i)} #{timestamp.inspect}"
end
puts
puts '=== 6. Relationship Cleanup ==='
puts 'Cleaning up relationships...'
domain1.remove_from_customer_domains(customer)
puts "✓ Removed #{domain1.name} from customer domains"
Domain.active_domains.remove(domain2.identifier)
puts "✓ Removed #{domain2.name} from active domains"
puts "\nAfter cleanup:"
puts " Customer domains: #{customer.domains.size}"
puts " Active domains: #{Domain.active_domains.size}"
puts
puts '=== Example Complete! ==='
puts
puts 'Key takeaways:'
puts '• class_tracked_in: Automatic class-level collections updated on save'
puts '• class_indexed_by: Automatic class-level indexes updated on save'
puts '• member_of: Use << operator for clean Ruby-like collection syntax'
puts '• indexed_by with parent:: Use for relationship-scoped indexes'
puts '• Save operations: Automatically update indexes and class-level tracking'
puts '• << operator: Works naturally with all collection types (sets, lists, sorted sets)'
puts
puts 'See docs/wiki/Relationships-Guide.md for comprehensive documentation'