Features are the core building blocks of Featury. Each feature represents an individual feature flag that can be enabled, disabled, or checked for status.
Use the feature method to define a feature flag:
class BillingFeature < ApplicationFeature
prefix :billing
feature :api
feature :webhooks
feature :invoicing
endThis creates three feature flags:
:billing_api:billing_webhooks:billing_invoicing
The prefix method defines a namespace for all features in the class:
class PaymentSystemFeature < ApplicationFeature
prefix :payment_system
feature :api # => :payment_system_api
feature :webhooks # => :payment_system_webhooks
end- Prefixes should use underscores:
user_onboarding,payment_system - Feature names should be concise:
api,webhooks,passage - Combined names use single underscores:
:user_onboarding_passage
Add descriptions to document what each feature does:
class BillingFeature < ApplicationFeature
prefix :billing
feature :api, description: "External billing API integration"
feature :webhooks, description: "Webhook endpoints for billing events"
feature :invoicing, description: "Automated invoice generation"
endDescriptions are preserved and accessible via the .info method:
BillingFeature.info.features.all
# => [
# { name: :billing_api, description: "External billing API integration" },
# { name: :billing_webhooks, description: "Webhook endpoints for billing events" },
# { name: :billing_invoicing, description: "Automated invoice generation" }
# ]You can define multiple related features in a single class:
class User::AccountFeature < ApplicationFeature
prefix :user_account
resource :user, type: User, option: true
feature :profile_editing, description: "Allow users to edit their profiles"
feature :avatar_upload, description: "Allow users to upload avatars"
feature :email_change, description: "Allow users to change their email"
feature :password_reset, description: "Enable password reset functionality"
endWhen you call actions on this class, they will operate on all four features:
User::AccountFeature.enabled?(user: user)
# Checks if ALL four features are enabled for this user
User::AccountFeature.enable(user: user)
# Enables ALL four features for this userBy default, Featury uses all-must-match logic:
class ApplicationFeature < Featury::Base
action :enabled?, web: :enabled? do |features:, **options|
features.all? { |feature| Flipper.enabled?(feature, *options.values) }
# Returns true only if ALL features are enabled
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
endYou can customize this behavior in your action definitions. See Actions for details.
To work with individual features, create separate classes:
class BillingAPIFeature < ApplicationFeature
prefix :billing
feature :api, description: "Billing API"
end
class BillingWebhooksFeature < ApplicationFeature
prefix :billing
feature :webhooks, description: "Billing webhooks"
end
# Now you can control them independently
BillingAPIFeature.enable(user: user)
BillingWebhooksFeature.disable(user: user)Or use your feature flag system directly for granular control:
Flipper.enable(:billing_api, user)
Flipper.disable(:billing_webhooks, user)Access all features including nested groups via .info.tree:
class MainFeature < ApplicationFeature
prefix :main
feature :alpha
feature :beta
group SubFeature, description: "Sub-features"
end
class SubFeature < ApplicationFeature
prefix :sub
feature :gamma
end
MainFeature.info.tree.features
# Direct features: [:main_alpha, :main_beta]
MainFeature.info.tree.groups
# Features from nested groups: [:sub_gamma]See Info and Introspection for complete details on the info API.
- Learn about Groups for organizing features hierarchically
- Add Resources for type-safe parameters
- Define Conditions for conditional feature activation
- See Examples for real-world feature definitions