Skip to content

Repository files navigation

Featury

Gem versionRelease 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:

classApplicationFeature < Featury::Baseaction:enabled?,web: :enabled?do |features:, **options|
features.all?{ |feature| Flipper.enabled?(feature, *options.values)}endaction:disabled?,web: :regulardo |features:, **options|
features.any?{ |feature| !Flipper.enabled?(feature, *options.values)}endaction:enable,web: :enabledo |features:, **options|
features.all?{ |feature| Flipper.enable(feature, *options.values)}endaction:disable,web: :disabledo |features:, **options|
features.all?{ |feature| Flipper.disable(feature, *options.values)}endaction:add,web: :regulardo |features:, **options|
features.all?{ |feature| Flipper.add(feature, *options.values)}endbeforedo |action:,features:|
Slack::API::Notify.call!(action:,features:)endafter:enabled?,:disabled?do |action:,features:|
Slack::API::Notify.call!(action:,features:)endend

Feature Definitions

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

classUser::OnboardingFeature < ApplicationFeatureprefix:user_onboardingresource:user,type: Usercondition->(resources:){resources.user.onboarding_awaiting?}feature:passage,description: "User onboarding passage feature"# => :user_onboarding_passagegroupBillingFeature,description: "Billing functionality group"groupPaymentSystemFeature,description: "Payment system functionality group"end
classBillingFeature < ApplicationFeatureprefix:billingfeature:api,description: "Billing API feature"# => :billing_apifeature:webhooks,description: "Billing webhooks feature"# => :billing_webhooksend
classPaymentSystemFeature < ApplicationFeatureprefix:payment_systemfeature:api,description: "Payment system API feature"# => :payment_system_apifeature:webhooks,description: "Payment system webhooks feature"# => :payment_system_webhooksend

Usage

# Direct method callsUser::OnboardingFeature.enabled?(user:)# => trueUser::OnboardingFeature.enable(user:)# => trueUser::OnboardingFeature.disable(user:)# => true# Using .with() methodfeature=User::OnboardingFeature.with(user:)feature.enabled?# => truefeature.enable# => truefeature.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.

Releases

Used by

Contributors

Languages