Skip to content

servactory/featury

Featury

Gem version Release Date

πŸ“š Documentation

See featury.servactory.com for comprehensive guides and API documentation.

Complete documentation is also available in the docs directory:

πŸ’‘ Why Featury?

  • 🎯 Unified Feature Management β€” Group and manage multiple feature flags through a single interface with automatic prefix handling
  • πŸ”Œ Flexible Integration β€” Works with any backend: Flipper, Redis, databases, HTTP APIs, or custom solutions
  • πŸ—‚οΈ Powerful Organization β€” Organize features with prefixes, groups, and nested hierarchies for scalable feature management
  • πŸ” Rich Introspection β€” Full visibility into features, actions, and resources through the comprehensive info API
  • πŸͺ Lifecycle Hooks β€” Before/after callbacks for actions with customizable scope and full context access
  • πŸ›‘οΈ Type-Safe Resources β€” Built on Servactory for robust resource validation, type checking, and automatic coercion

πŸš€ Quick Start

Installation

Add Featury to your Gemfile:

gem "featury"

ApplicationFeature

Create a base class that defines how features interact with your feature flag system:

class ApplicationFeature < Featury::Base
  action :enabled?, web: :enabled? do |features:, **options|
    features.all? { |feature| Flipper.enabled?(feature, *options.values) }
  end

  action :disabled?, web: :regular do |features:, **options|
    features.any? { |feature| !Flipper.enabled?(feature, *options.values) }
  end

  action :enable, web: :enable do |features:, **options|
    features.all? { |feature| Flipper.enable(feature, *options.values) }
  end

  action :disable, web: :disable do |features:, **options|
    features.all? { |feature| Flipper.disable(feature, *options.values) }
  end

  action :add, web: :regular do |features:, **options|
    features.all? { |feature| Flipper.add(feature, *options.values) }
  end

  before do |action:, features:|
    Slack::API::Notify.call!(action:, features:)
  end

  after :enabled?, :disabled? do |action:, features:|
    Slack::API::Notify.call!(action:, features:)
  end
end

Feature Definitions

Define features with prefixes, resources, conditions, and groups:

class User::OnboardingFeature < ApplicationFeature
  prefix :user_onboarding

  resource :user, type: User

  condition ->(resources:) { resources.user.onboarding_awaiting? }

  feature :passage, description: "User onboarding passage feature" # => :user_onboarding_passage

  group BillingFeature, description: "Billing functionality group"
  group PaymentSystemFeature, description: "Payment system functionality group"
end
class BillingFeature < ApplicationFeature
  prefix :billing

  feature :api, description: "Billing API feature"        # => :billing_api
  feature :webhooks, description: "Billing webhooks feature"    # => :billing_webhooks
end
class PaymentSystemFeature < ApplicationFeature
  prefix :payment_system

  feature :api, description: "Payment system API feature"      # => :payment_system_api
  feature :webhooks, description: "Payment system webhooks feature"  # => :payment_system_webhooks
end

Usage

# Direct method calls
User::OnboardingFeature.enabled?(user:) # => true
User::OnboardingFeature.enable(user:)   # => true
User::OnboardingFeature.disable(user:)  # => true

# Using .with() method
feature = User::OnboardingFeature.with(user:)
feature.enabled? # => true
feature.enable   # => true
feature.disable  # => true

🀝 Contributing

This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the Contributor Covenant code of conduct. We recommend reading the contributing guide as well.

πŸ™ Acknowledgments

Featury is built and maintained by amazing contributors.

πŸ“„ License

Featury is available as open source under the terms of the MIT License.

Contributors 2

  •  
  •  

Languages