Skip to main content

Quick Start

Get up and running with Toggly in minutes.

Basic Usage​

Create a Client​

A feature flag is a named boolean decision. Create ExpressCheckout in your Toggly app and environment, then set TOGGLY_APP_KEY in your process environment. Start with the flag disabled; enable it and run the script again to see the result change. Without a key this example uses its explicit offline default (false).

checkout.rb
require 'toggly'

# One definitions client per process. Without a key, these nonempty
# defaults select offline mode; with a key, startup fetches definitions.
client = Toggly::Client.new(
app_key: ENV['TOGGLY_APP_KEY'],
environment: 'Production',
defaults: { 'ExpressCheckout' => false }
)
begin
# Example values: in a web app use the authenticated user and an
# Order that the user is authorized to access, before the first check.
context = Toggly::Context.new(
identity: 'user-123', groups: ['premium'],
claims: { 'role' => 'customer' },
request: Toggly::RequestContext.new(
user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
accept_language: 'en-US,en;q=0.9', country: 'US'
),
entity: Toggly::EntityContext.new(
kind: 'Order', key: 'order-42',
attributes: { 'Vip' => true, 'Total' => 149.95 }
)
)
puts client.enabled?('ExpressCheckout', context: context)
ensure
client.close # Scripts own cleanup; services close at process shutdown.
end

Check Features​

The constructor starts the client and performs its initial app/environment definitions fetch. It does not send user context. Each enabled? call evaluates locally using the context supplied for that request. Build that context before its first corresponding check, even though application startup happened earlier.

Within the begin block above, these calls use the same request context:

client.disabled?('ExpressCheckout', context: context)
client.enabled?('unknown-feature', context: context, default: false)
result = client.evaluate('ExpressCheckout', context: context)
puts result.to_h # feature_key, enabled, reason, matched_rule, matched_rule_index

evaluate is boolean diagnostics, not variant allocation. Unlike enabled?, it does not apply unknown-feature defaults or record an automatic check. A global flag with no targeting can be checked without a context.

Global Configuration​

For a long-running non-Rails service, use this alternative startup configuration once. Do not also construct the script client above.

require 'toggly'
Toggly.configure do |config|
config.app_key = ENV['TOGGLY_APP_KEY']
config.environment = 'Production'
config.defaults = { 'ExpressCheckout' => false }
# Explicit in block configuration; these values are core-only options.
config.enable_usage_tracking = true
config.enable_metrics = true
end
at_exit { Toggly.reset! } # Closes and clears the process-owned client.

In request handling, call Toggly.enabled?('ExpressCheckout', context: context) with that request's context. Do not reconfigure or mutate shared identity per request. See telemetry setup for optional transport dependencies.

For a complete single-process Rack/Puma application, see the Ruby SDK sample. Its process startup and shutdown keeps one definitions client for the serving process and closes it at exit. With Puma, keep mutex-using SDK cleanup outside a raw signal trap.

The Rack sample injects a local telemetry capture transport for teaching, including when definitions come from a configured app. Captured batches are not remote delivery. For native remote senders and the Rails core-options initializer, see Usage and metrics and Rails note.

Rails Quick Start​

1. Add to Gemfile​

Gemfile
gem 'toggly-rails'

2. Install​

bundle install
rails generate toggly:install

3. Configure​

config/initializers/toggly.rb
Toggly::Rails.configure do |config|
config.app_key = Rails.application.credentials.dig(:toggly, :app_key)
config.environment = Rails.env.production? ? 'Production' : 'Staging'
config.defaults = { 'ExpressCheckout' => false, 'new_dashboard' => false }
end

The Railtie installs the controller concern and view helpers and closes the client at exit. Its default context maps identity/groups/traits/entity; add the complete builder for claims and structured request fields. Load authenticated state and the authorized Order in a prepend_before_action before the SDK caches the first context, as shown in Rails entity context.

4. Use in Controllers​

app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
if feature_enabled?(:new_product_list)
@products = Product.includes(:images).all
render :index_v2
else
@products = Product.all
render :index
end
end
end

5. Use in Views​

app/views/products/index.html.erb
<%= feature(:show_ratings) do %>
<% @products.each do |product| %>
<div class="ratings">
<%= render product.ratings %>
</div>
<% end %>
<% end %>
<%= feature(:show_ratings, negate: true) do %>
<p>Ratings are not available.</p>
<% end %>

The controller supplies a collection in @products. Each product must expose a ratings association; Rails renders each rating through app/views/ratings/_rating.html.erb, passing it as the rating local. For a rating model with a score attribute:

app/views/ratings/_rating.html.erb
<p><%= rating.score %> / 5</p>

The example controller also expects an app/views/products/index_v2.html.erb template when new_product_list is enabled. Use the same collection/partial contract there.

User Targeting​

Use a stable authenticated user ID in identity, audience memberships in groups, verified principal values in claims, and normalized request fields in request. entity describes one Order, independently of who is viewing it. The first example supplies all of these before evaluation. See User Context for request mapping and changing Orders.

Offline Mode​

This separate example omits app_key and uses nonempty defaults. Missing both a key and defaults raises Toggly::ConfigError; disabling background refresh alone does not prevent the initial fetch.

client = Toggly::Client.new(
defaults: {
'feature-a' => true,
'feature-b' => false
}
)

client.enabled?('feature-a') # => true
client.enabled?('feature-b') # => false
client.enabled?('feature-c') # => false (unknown defaults to false)
client.close

Next Steps​