Created
December 6, 2016 16:47
-
-
Save wojtha/43c68be62757d0b7030485efcf13583b to your computer and use it in GitHub Desktop.
Feature flags in 20 LOC for ruby apps based on http://blog.arkency.com/2015/11/simple-feature-toggle-for-rails-app/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Class FeatureFlag defines and stores feature flags | |
# | |
# @see http://blog.arkency.com/2015/11/simple-feature-toggle-for-rails-app/ | |
# | |
class FeatureFlag | |
def initialize | |
@flags = {} | |
yield self if block_given? | |
end | |
def define(name, &block) | |
@flags[name] = block | |
end | |
def flags | |
@flags.keys | |
end | |
def with(name, *args, &block) | |
block.call if active?(name, *args) | |
end | |
def active?(name, *args) | |
@flags.fetch(name, proc{ |*_args| false }).call(*args) | |
end | |
def inactive?(name, *args) | |
!active?(name, *args) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'feature_flag' | |
describe FeatureFlag do | |
describe '#initialize' do | |
it 'yields self to allow better setup' do | |
expect{ |b| described_class.new(&b) }.to yield_with_args(FeatureFlag) | |
end | |
it 'allows definition of features within the yielded block' do | |
features = described_class.new do |feature| | |
feature.define(:flag1) | |
feature.define('flag2') | |
end | |
expect( features.flags ).to have(2).items | |
expect( features.flags ).to include :flag1, 'flag2' | |
end | |
end | |
describe '#define' do | |
it 'defines flag' do | |
subject.define 'flag' | |
expect( subject.flags ).to include 'flag' | |
end | |
end | |
describe '#flags' do | |
context 'when no flag is defined' do | |
it 'returns empty array' do | |
expect( subject.flags ).to eq [] | |
end | |
end | |
context 'when flags are defined' do | |
it 'contains defined flag names' do | |
subject.define(:flag1) | |
subject.define('flag2') | |
expect( subject.flags ).to have(2).items | |
expect( subject.flags ).to include :flag1, 'flag2' | |
end | |
end | |
end | |
describe '#active?' do | |
context 'when flag is truthy' do | |
it 'returns true' do | |
subject.define(:flag) { true } | |
expect( subject.active?(:flag) ).to eq true | |
end | |
end | |
context 'when flag is falsy' do | |
it 'returns false' do | |
subject.define(:flag) { false } | |
expect( subject.active?(:flag) ).to eq false | |
end | |
end | |
context 'when flag is not defined' do | |
it 'returns false' do | |
expect( subject.active?(:flag) ).to eq false | |
end | |
end | |
end | |
describe '#inactive?' do | |
context 'when flag is truthy' do | |
it 'returns false' do | |
subject.define(:flag) { true } | |
expect( subject.inactive?(:flag) ).to eq false | |
end | |
end | |
context 'when flag is falsy' do | |
it 'returns true' do | |
subject.define(:flag) { false } | |
expect( subject.inactive?(:flag) ).to eq true | |
end | |
end | |
context 'when flag is not defined' do | |
it 'returns true' do | |
expect( subject.inactive?(:flag) ).to eq true | |
end | |
end | |
end | |
describe '#with &block' do | |
context 'when flag is truthy' do | |
it 'calls the block' do | |
subject.define(:flag) { true } | |
probe = lambda{} | |
expect( probe ).to receive(:call) | |
subject.with(:flag, &probe) | |
end | |
end | |
context 'when flag is falsy' do | |
it 'does not call the block' do | |
subject.define(:flag) { false } | |
probe = lambda{} | |
expect( probe ).not_to receive(:call) | |
subject.with(:flag, &probe) | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FEATURE = FeatureFlag.new do |feature| | |
feature.define(:new_user_profile) do |user_id:| | |
Admin.where(user_id: user_id).exists? | |
end | |
feature.define(:third_party_analytics) do | |
not Rails.env.production? | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment