Feature Toggles

Services & Skills

Share on

Framework-agnostic usage

Features could be defined dynamically:

features = FeatureToggles.build do
  # define env var prefix to enable features
  # globally by passing MY_PREFIX_BAR=1
  env "MY_PREFIX"

  feature :bar do
    user.can_bar?
  end

  feature :foo do |user: nil|
    !user.nil? && user.can_foo?
  end
end

features.enabled?(:bar)
features.enabled?(:bar, user: user)
features.for(user: user).enabled?(:foo)

or loaded from files:

features = FeatureToggles.build(["/path/to/features.rb"])

Rails usage

This is step-by-step guide to add feature_toggles to Rails application.

Step 0. (optional) Add features to User model

class AddFeaturesToUsers < ActiveRecord::Migration
  def change
    # we use a `features` array column to store user's active features
    add_column :users, :features, :string, array: true, default: []
  end
end

Step 1. Define features

Features from file <rails-root-or-engine>/config/features.rb are loaded by convention.

# config/features.rb
env "FEATURE"

feature :chat do |user: nil|
  user&.features.include?("chat")
end

Features will be available at Rails.features after the end of application initialization.

Step 2. Add current_features helper and use it.

class ApplicationController < ActionController::Base
  # ...
  helper_method :current_features

  def current_features
    Rails.features.for(user: current_user)
  end
end

Step 3. Use current_features.

For example, in your navigation template:

<ul>
 <% if current_features.enabled?(:chat) %>
   <li><a href="/chat">Chat</a></li>
 <% end %>
</ul>

Or in your controller:

class ChatController < ApplicationController
  def index
    unless current_features.enabled?(:chat)
      return render template: "comming_soon"
    end
  end
end

Metadata

You can add arbitrary metadata to features:

feature :manual_quantity_backsync, icon: :updated, description: "Manual quantity sync for imported products" do |user: nil|
  !!user&.features&.fetch("manual_quantity_backsync", false)
end

That metadata can be later programmatically accessed and exposed into admin panels, API documentation, etc.

Rails.features.first.metadata
# => { icon: :updated, description: "Manual quantity sync for imported products" }
Author

In the same orbit

Explore more open source projects

Contact us

We’d love to hear from you! We’re not really all that evil, and we love discussing potential projects, intriguing ideas, and new opportunities. Complete the form below or drop us a line at surrender@evilmartians.com.

Martians at a glance
16
years in business

A product development consultancy that works with startups and established businesses, while also creating open source-based products and services