0.0
No release in over 3 years
Real-time feature flags with SSE streaming, local evaluation, and smart caching
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 3.12
~> 1.59
~> 0.22
~> 3.19

Runtime

 Project Readme

ToggleCraft Ruby SDK

A lightweight, real-time feature flag SDK for Ruby applications. Thread-safe, Rails-friendly, and built for production.

Why ToggleCraft?

  • ๐Ÿš€ Real-time Updates - Instant flag changes via Server-Sent Events
  • ๐Ÿงต Thread-Safe - Built for Puma, Sidekiq, and multi-threaded environments
  • ๐Ÿ’พ Smart Caching - Works offline with memory or Redis support
  • ๐Ÿ”’ Production Ready - 214 passing tests with comprehensive coverage
  • ๐ŸŒ Universal - Works with Rails, Sinatra, Hanami, and standalone Ruby
  • โ™ป๏ธ Auto-reconnection - Resilient connection handling

Installation

Add to your Gemfile:

gem 'togglecraft'

Or install directly:

gem install togglecraft

Quick Start

Ruby

require 'togglecraft'

# Initialize client
client = ToggleCraft::Client.new(sdk_key: 'your-sdk-key')

# Connect and wait for flags
client.connect
client.wait_for_ready

# Use your flags
if client.enabled?('new-feature', user: { id: current_user.id })
  # Feature is enabled
end

Rails

# config/initializers/togglecraft.rb
Rails.application.config.togglecraft = ToggleCraft::Client.new(
  sdk_key: ENV['TOGGLECRAFT_SDK_KEY'],
  cache_adapter: :memory,
  logger: Rails.logger,
  debug: Rails.env.development?
)

Rails.application.config.togglecraft.connect

at_exit do
  Rails.application.config.togglecraft.destroy
end

Then use in your controllers:

class DashboardController < ApplicationController
  def index
    if togglecraft.enabled?('premium-dashboard', user: { id: current_user.id })
      render :premium
    else
      render :standard
    end
  end

  private

  def togglecraft
    Rails.application.config.togglecraft
  end
end

Basic Usage

Boolean Flags

Simple on/off feature toggles:

if client.enabled?('dark-mode', user: { id: '123' })
  enable_dark_mode
end

Multivariate Flags

A/B/n testing with multiple variants:

variant = client.variant('checkout-flow', user: { id: '123' })

case variant
when 'one-page'
  render_one_page_checkout
when 'multi-step'
  render_multi_step_checkout
else
  render_default_checkout
end

Percentage Rollouts

Gradual feature rollouts:

if client.in_percentage?('new-algorithm', user: { id: '123' })
  use_new_algorithm
else
  use_legacy_algorithm
end

Configuration

client = ToggleCraft::Client.new(
  # Required
  sdk_key: 'your-sdk-key',              # Get from ToggleCraft dashboard

  # Optional - Common settings
  enable_cache: true,                   # Enable caching (default: true)
  cache_adapter: :memory,               # :memory or :redis (default: :memory)
  cache_ttl: 300,                       # Cache TTL in seconds (default: 5 minutes)
  debug: false                          # Enable debug logging (default: false)
)

Need more control? See Advanced Configuration โ†’

Evaluation Context

The context object provides data for targeting rules:

context = {
  user: {
    id: 'user-123',                     # Required for consistent evaluation
    email: 'user@example.com',
    plan: 'premium',
    # Add any custom attributes you need
    role: 'admin',
    company_id: 'acme-corp'
  },
  request: {
    ip: '192.168.1.1',
    country: 'US'
  },
  device: {
    type: 'mobile',
    os: 'iOS'
  }
}

client.enabled?('premium-feature', context)

You can add any custom properties - the SDK evaluates all attributes using dot notation (e.g., user.role, request.country).

Framework Integration

Rails

# config/initializers/togglecraft.rb
Rails.application.config.togglecraft = ToggleCraft::Client.new(
  sdk_key: ENV['TOGGLECRAFT_SDK_KEY'],
  cache_adapter: :memory,
  logger: Rails.logger
)

Full Rails Integration Guide โ†’

Sidekiq

class FeatureWorker
  include Sidekiq::Worker

  def togglecraft
    @togglecraft ||= ToggleCraft::Client.new(
      sdk_key: ENV['TOGGLECRAFT_SDK_KEY'],
      share_connection: true  # Share connection with other workers
    )
  end

  def perform(user_id)
    togglecraft.connect unless togglecraft.connected?

    if togglecraft.enabled?('batch-processing', user: { id: user_id })
      # Use new batch processing
    end
  end
end

Full Sidekiq Integration Guide โ†’

Event Handling

Listen for real-time updates:

# Flags are ready
client.on(:ready) do
  puts 'Client ready!'
end

# Flags updated in real-time
client.on(:flags_updated) do |flags|
  puts "Flags updated: #{flags.keys.join(', ')}"
end

# Connection lost
client.on(:disconnected) do
  puts 'Disconnected - using cached flags'
end

# Error occurred
client.on(:error) do |error|
  logger.error "ToggleCraft error: #{error}"
end

Error Handling

Always provide default values and handle errors gracefully:

# Safe evaluation with defaults
is_enabled = client.enabled?('feature', context, default: false)
# Returns false if flag doesn't exist or on error

# Handle connection errors
begin
  client.connect
rescue StandardError => e
  logger.error "Failed to connect: #{e}"
  # App still works with cached values or defaults
end

Best Practices

  1. Initialize Once - Create a single client instance and reuse it
  2. Always Provide Context - Include at least user.id for consistent evaluation
  3. Use Default Values - Handle missing flags gracefully
  4. Clean Up on Shutdown - Call client.destroy when closing
# On application shutdown
at_exit do
  client.destroy
end

API Reference

Core Methods:

  • enabled?(flag_key, context = {}, default: false) - Check boolean flags
  • variant(flag_key, context = {}, default: nil) - Get multivariate variant
  • in_percentage?(flag_key, context = {}, default: false) - Check percentage rollout

Connection:

  • connect - Connect to SSE server
  • disconnect - Disconnect from server
  • ready? - Check if client has flags loaded
  • wait_for_ready(timeout: 5) - Wait for client to be ready

Full API Documentation โ†’

Advanced Features

Power users can customize:

  • Connection pooling and reconnection strategies
  • Scheduled rollout stages with automatic transitions
  • Redis cache adapter
  • Hybrid reconnection with exponential backoff

Advanced Features Guide โ†’

Troubleshooting

Client not connecting?

  • Verify your SDK key is correct
  • Check that you called connect before using the client
  • Ensure your firewall allows connections to sse.togglecraft.io

Flags not updating?

  • Verify the SSE connection is established (client.connected?)
  • Check the logs for error messages
  • Enable debug mode: debug: true

More Troubleshooting โ†’

Requirements

  • Ruby 3.0+
  • Dependencies:
    • concurrent-ruby (~> 1.2) - Thread-safe data structures
    • http (~> 5.0) - HTTP client for API requests
    • semantic (~> 1.6) - Semantic version comparison

Thread Safety

This SDK is fully thread-safe and production-ready for:

  • Puma - Multi-threaded Rails server
  • Sidekiq - Background job processing
  • Any multi-threaded Ruby environment

All critical sections use Concurrent::Map, Mutex, and Concurrent::AtomicBoolean for thread safety.

Documentation

License

MIT

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

Support