feature_toggle 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +0 -0
- data/README.md +52 -0
- data/Rakefile +0 -0
- data/lib/feature_toggle.rb +11 -0
- data/lib/feature_toggle/features.rb +53 -0
- data/test/feature_toggle_test.rb +60 -0
- data/test/features.yml +11 -0
- metadata +71 -0
data/CHANGELOG.md
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
# FeatureToggle
|
3
|
+
|
4
|
+
FeatureToggle is a [feature toggle](http://martinfowler.com/bliki/FeatureToggle.html) library for ruby.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
gem install feature_toggle
|
9
|
+
|
10
|
+
## Examples
|
11
|
+
|
12
|
+
### Rails
|
13
|
+
|
14
|
+
# File: Gemfile
|
15
|
+
gem 'feature_toggle'
|
16
|
+
|
17
|
+
# File: config/features.yml
|
18
|
+
feature1:
|
19
|
+
controller1:
|
20
|
+
- action1
|
21
|
+
- action2
|
22
|
+
controller2:
|
23
|
+
- action1
|
24
|
+
- action2
|
25
|
+
feature2:
|
26
|
+
controller3:
|
27
|
+
- action1
|
28
|
+
- action2
|
29
|
+
feature3:
|
30
|
+
controller4:
|
31
|
+
- action1
|
32
|
+
- action2
|
33
|
+
|
34
|
+
# File: config/initializers/feature_toggle.rb
|
35
|
+
FEATURES = FeatureToggle.load(File.join(RAILS_ROOT, 'config', 'features.yml'))
|
36
|
+
FEATURES.deactivate('feature1', 'feature2', 'feature3')
|
37
|
+
|
38
|
+
# File: app/controllers/application_controller.rb
|
39
|
+
before_filter :check_feature_activated?
|
40
|
+
|
41
|
+
def check_feature_activated?
|
42
|
+
FEATURES.active_action?(params[:controller], params[:action])
|
43
|
+
end
|
44
|
+
|
45
|
+
# File: app/views/example/index.html.erb
|
46
|
+
<% if FEATURES.active?('feature1') %>
|
47
|
+
<%# Feature implementation goes here %>
|
48
|
+
<% end %>
|
49
|
+
<% if FEATURES.active_action?('controller4', 'action1') %>
|
50
|
+
<%# Feature implementation goes here %>
|
51
|
+
<% end %>
|
52
|
+
|
data/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'set'
|
2
|
+
module FeatureToggle
|
3
|
+
class Features
|
4
|
+
def initialize(features)
|
5
|
+
@features = features
|
6
|
+
@actions = build_actions_feature_map(features)
|
7
|
+
@deactivated_features = Set.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](feature_name)
|
11
|
+
@features[feature_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
def activate(*feature_names)
|
15
|
+
feature_names.each do |feature_name|
|
16
|
+
validate!(feature_name)
|
17
|
+
@deactivated_features.delete(feature_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def deactivate(*feature_names)
|
22
|
+
feature_names.each do |feature_name|
|
23
|
+
validate!(feature_name)
|
24
|
+
@deactivated_features << feature_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def active_action?(controller, action)
|
29
|
+
feature = @actions["#{controller}:#{action}"]
|
30
|
+
active?(feature)
|
31
|
+
end
|
32
|
+
|
33
|
+
def active?(feature_name)
|
34
|
+
!@deactivated_features.include?(feature_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def validate!(feature_name)
|
39
|
+
raise UnknownFeatureError, "Unknown feature name: #{feature_name}" unless @features.has_key?(feature_name)
|
40
|
+
end
|
41
|
+
def build_actions_feature_map(features)
|
42
|
+
map = {}
|
43
|
+
features.each do |feature, controllers|
|
44
|
+
controllers.each do |controller_name, actions|
|
45
|
+
actions.each do |action_name|
|
46
|
+
map["#{controller_name}:#{action_name}"] = feature
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
map
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
require "feature_toggle"
|
4
|
+
|
5
|
+
class FeatureToggleTest < Test::Unit::TestCase
|
6
|
+
def test_load_features
|
7
|
+
features = load_features
|
8
|
+
assert_equal({'users' => ['update', 'show']}, features['user_profile'])
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_can_deactivate_features
|
12
|
+
features = load_features
|
13
|
+
assert features.active?('user_profile')
|
14
|
+
|
15
|
+
features.deactivate("user_profile")
|
16
|
+
assert !features.active?('user_profile')
|
17
|
+
|
18
|
+
features.deactivate("wpc", "rao")
|
19
|
+
assert !features.active?('wpc')
|
20
|
+
assert !features.active?('rao')
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_activate_feature_after_deactivated_feature
|
24
|
+
features = load_features
|
25
|
+
features.deactivate("user_profile")
|
26
|
+
features.activate("user_profile")
|
27
|
+
assert features.active?('user_profile')
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_disabling_non_existent_features_should_raise_error
|
31
|
+
features = load_features
|
32
|
+
assert_raises FeatureToggle::UnknownFeatureError do
|
33
|
+
features.deactivate("user")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_activating_non_existent_features_should_raise_error
|
38
|
+
features = load_features
|
39
|
+
assert_raises FeatureToggle::UnknownFeatureError do
|
40
|
+
features.activate("user")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_feature_actions_should_be_active_when_feature_is_active
|
45
|
+
features = load_features
|
46
|
+
assert features.active_action?('users', 'update')
|
47
|
+
features.deactivate("user_profile")
|
48
|
+
assert !features.active_action?('users', 'update')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_feature_action_should_be_active_when_no_feature_defines_the_action
|
52
|
+
features = load_features
|
53
|
+
assert features.active_action?('users', 'destroy')
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_features
|
57
|
+
config = File.join(File.dirname(__FILE__), 'features.yml')
|
58
|
+
FeatureToggle.load(config)
|
59
|
+
end
|
60
|
+
end
|
data/test/features.yml
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: feature_toggle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mingle SaaS team
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-07-31 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: mingle.saas@thoughtworks.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/feature_toggle/features.rb
|
31
|
+
- lib/feature_toggle.rb
|
32
|
+
- test/feature_toggle_test.rb
|
33
|
+
- test/features.yml
|
34
|
+
- Rakefile
|
35
|
+
- README.md
|
36
|
+
- CHANGELOG.md
|
37
|
+
homepage: https://github.com/ThoughtWorksStudios/feature_toggle
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.8.24
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Feature Toggle library for ruby
|
70
|
+
test_files: []
|
71
|
+
|