feature_flipper 1.1.0 → 1.2.0

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/README.md CHANGED
@@ -18,6 +18,36 @@ configuration file after requiring FeatureFlipper:
18
18
  require 'feature_flipper'
19
19
  FeatureFlipper::Config.path_to_file = "#{RAILS_ROOT}/config/features.rb"
20
20
 
21
+ Example config file
22
+ -------------------
23
+
24
+ FeatureFlipper.features do
25
+ in_state :development do
26
+ feature :rating_game, :description => 'play a game to get recommendations'
27
+ end
28
+
29
+ in_state :live do
30
+ feature :city_feed, :description => 'stream of content for each city'
31
+ end
32
+ end
33
+
34
+ FeatureFlipper::Config.states = {
35
+ :development => ['development', 'test'].include?(Rails.env),
36
+ :live => true
37
+ }
38
+
39
+ This is your complete features.rb config file. In the example there are two
40
+ states: `:development` is active on development boxes and `:live` is always active
41
+ (this is the last state a feature goes through).
42
+
43
+ The feature `:rating_game` is still in development and not shown on the
44
+ production site. The feature `:city_feed` is done and already enabled
45
+ everywhere. You transition features between states by just moving the line to
46
+ the new state block.
47
+
48
+ You can take a look at the `static_states.rb` in the examples folder to
49
+ see this in detail.
50
+
21
51
  Configuration
22
52
  -------------
23
53
 
@@ -27,10 +57,11 @@ FeatureFlipper cares about:
27
57
  * states
28
58
  * features
29
59
 
30
- You first define multiple 'states' which normally depend on an environment
31
- (for example: the state 'dev' is only active on development boxes). After that
32
- you add 'features' which correspond to logical chunks of work in your project.
33
- These features then move through the different states as they get developed.
60
+ You first define multiple 'states' which normally depend on the environment
61
+ (for example: the state 'development' is only active on development boxes).
62
+ After that you add 'features' which correspond to logical chunks of work in
63
+ your project. These features then move through the different states
64
+ as they get developed (for example: :development -> :staging -> :live).
34
65
 
35
66
  ### Defining features
36
67
 
@@ -39,22 +70,24 @@ more detailed description, a ticket number, a date when it was started, etc.
39
70
  Features are always defined in a state, you cannot define a feature which
40
71
  doesn't belong to a state.
41
72
 
42
- in_state :dev do
73
+ in_state :development do
43
74
  feature :rating_game, :description => 'play a game to get recommendations'
44
75
  end
45
76
 
46
77
  ### Defining states
47
78
 
48
79
  A state is just a name and a boolean check. The check needs to evaluate to
49
- ´true´ when it is active. For a Rails app you can just use environments:
80
+ `true` when it is active. For a Rails app you can just use environments:
50
81
 
51
- :dev => ['development', 'test'].include?(Rails.env),
82
+ FeatureFlipper::Config.states = {
83
+ :development => ['development', 'test'].include?(Rails.env)
84
+ }
52
85
 
53
86
  Usage
54
87
  -----
55
88
 
56
89
  In your code you then use the `show_feature?` method to branch depending on
57
- wether the feature is active or not:
90
+ wether a feature is active or not:
58
91
 
59
92
  if show_feature?(:rating_game)
60
93
  # new code
@@ -64,42 +97,12 @@ wether the feature is active or not:
64
97
 
65
98
  The `show_feature?` method is defined on Object, so you can use it everywhere.
66
99
 
67
- Example config file
68
- -------------------
69
-
70
- FeatureFlipper.features do
71
- in_state :dev do
72
- feature :rating_game, :description => 'play a game to get recommendations'
73
- end
74
-
75
- in_state :live do
76
- feature :city_feed, :description => 'stream of content for each city'
77
- end
78
- end
79
-
80
- FeatureFlipper::Config.states = {
81
- :dev => ['development', 'test'].include?(Rails.env),
82
- :live => true
83
- }
84
-
85
- This is your complete features.rb config file. In the example there are two
86
- states: `:dev` is active on development boxes and `:live` is always active
87
- (this is the last state a feature goes through).
88
-
89
- The feature `:rating_game` is still in development and not shown on the
90
- production site. The feature `:city_feed` is done and already enabled
91
- everywhere. You transition features between states by just moving the line to
92
- the new state block.
93
-
94
- You can take a look at the `static_states.rb` in the 'examples' folder to
95
- see this in detail.
96
-
97
100
  Cleaning up
98
101
  -----------
99
102
 
100
103
  The drawback of this approach is that your code can get quite ugly with all
101
- these if/else branches. So you have to be strict about removing (we call it
102
- de-featurizing) features after they have gone live.
104
+ these if/else branches. So you have to be strict about removing features
105
+ (we call it de-featurizing) after they have gone live.
103
106
 
104
107
  Dynamic feature groups
105
108
  ----------------------
@@ -107,43 +110,45 @@ Dynamic feature groups
107
110
  As soon as we have the feature_flipper infrastructure in place, we can start
108
111
  doing more interesting things with it. For example, dynamic features which
109
112
  are enabled on a per user basis. This allows you to release features to
110
- employees only, to a private beta group, etc.
113
+ employees only or to a private beta group, etc.
111
114
 
112
115
  ### Defining dynamic states
113
116
 
114
117
  A dynamic state is defined a bit different than a normal, static state.
115
118
 
116
119
  FeatureFlipper::Config.states = {
117
- :dev => ['development', 'test'].include?(Rails.env),
118
- :employees => { :required_state => :dev, :feature_group => :employees }
120
+ :development => ['development', 'test'].include?(Rails.env),
121
+ :employees => { :required_state => :development, :feature_group => :employees }
119
122
  }
120
123
 
121
124
  It has a required state and a feature group. The feature group defines
122
- the name of the group of users which should see this feature. The required
123
- state is the state that gets looked at for all other users that aren't in
124
- the feature group. The required_state must also be defined as a separate state.
125
+ a symbolic name for the group of users who should see this feature. You
126
+ can name this whatever you want. The required state is the state that gets
127
+ looked at for all other users that aren't in the feature group. The required
128
+ state (:development) must be a defined, static state.
125
129
 
126
130
  ### Setting the feature group
127
131
 
128
- The current feature group is set globally and is active for the whole thread.
132
+ The feature group is set globally and is active for the whole thread.
129
133
  In Rails you would define a before_filter like this:
130
134
 
131
135
  class ApplicationController < ActionController::Base
132
- before_filter :set_current_feature_group
136
+ before_filter :set_active_feature_group
133
137
 
134
- def set_current_feature_group
138
+ def set_active_feature_group
135
139
  # we need to reset the feature group in each request,
136
- # otherwise it persists (which is not want we want).
137
- FeatureFlipper.reset_current_feature_groups
140
+ # otherwise it's also active for the following requests.
141
+ FeatureFlipper.reset_active_feature_groups
138
142
 
139
143
  if logged_in? && current_user.employee?
140
- FeatureFlipper.current_feature_groups << :employees
144
+ FeatureFlipper.active_feature_groups << :employees
141
145
  end
142
146
  end
143
147
 
144
- It's really important to reset the feature group, otherwise it's not dynamic.
145
- The condition if someone is in a feature group can be anything: You can
146
- store it in the database, in Redis, look at request parameters, etc.
148
+ Don't forget to reset the feature group, without it the feature group
149
+ is active forever. The condition if someone is in a feature group
150
+ can be anything: You can store it in the database, in Redis,
151
+ look at request parameters, based on the current time, etc.
147
152
 
148
153
  Take a look at `dynamic_states.rb` in the examples folder to see this
149
154
  in detail.
@@ -26,7 +26,7 @@ FeatureFlipper::Config.path_to_file = "features.rb"
26
26
 
27
27
  puts "=== first example:"
28
28
 
29
- # no current_feature_group set, so the required_state of badges is looked at
29
+ # no active feature_group set, so the required_state of badges is looked at
30
30
  if show_feature?(:badges)
31
31
  puts "shiny new badges not live on prod yet"
32
32
  else
@@ -35,10 +35,10 @@ end
35
35
 
36
36
  puts "\n=== second example:"
37
37
 
38
- # now we set the current_feature_group. Usually depending on the logged in user
38
+ # now we set the active feature_group. Usually depending on the logged in user
39
39
 
40
- FeatureFlipper.reset_current_feature_groups
41
- FeatureFlipper.current_feature_groups << :employees
40
+ FeatureFlipper.reset_active_feature_groups
41
+ FeatureFlipper.active_feature_groups << :employees
42
42
 
43
43
  if show_feature?(:badges)
44
44
  puts "shiny new badges for this user"
data/examples/features.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
 
6
6
  FeatureFlipper.features do
7
- in_state :dev do
7
+ in_state :development do
8
8
  feature :rating_game, :description => 'play a game to get recommendations'
9
9
  end
10
10
 
@@ -18,7 +18,7 @@ FeatureFlipper.features do
18
18
  end
19
19
 
20
20
  FeatureFlipper::Config.states = {
21
- :dev => ['development', 'test'].include?(Rails.env),
22
- :employees => { :required_state => :dev, :feature_group => :employees },
23
- :live => true
21
+ :development => ['development', 'test'].include?(Rails.env),
22
+ :employees => { :required_state => :development, :feature_group => :employees },
23
+ :live => true
24
24
  }
@@ -51,7 +51,7 @@ module FeatureFlipper
51
51
  else
52
52
  group, required_state = active.to_a.flatten
53
53
  end
54
- (FeatureFlipper.current_feature_groups.include?(group)) || (states[required_state] == true)
54
+ (FeatureFlipper.active_feature_groups.include?(group)) || (states[required_state] == true)
55
55
  else
56
56
  active == true
57
57
  end
@@ -91,11 +91,11 @@ module FeatureFlipper
91
91
  StateMapper.new.instance_eval(&block)
92
92
  end
93
93
 
94
- def self.current_feature_groups
95
- Thread.current[:feature_system_current_feature_groups] ||= []
94
+ def self.active_feature_groups
95
+ Thread.current[:feature_system_active_feature_groups] ||= []
96
96
  end
97
97
 
98
- def self.reset_current_feature_groups
99
- current_feature_groups.clear
98
+ def self.reset_active_feature_groups
99
+ active_feature_groups.clear
100
100
  end
101
101
  end
@@ -1,3 +1,3 @@
1
1
  module FeatureFlipper
2
- Version = VERSION = '1.1.0'
2
+ Version = VERSION = '1.2.0'
3
3
  end
@@ -76,12 +76,12 @@ context 'dynamic feature groups' do
76
76
  setup do
77
77
  FeatureFlipper::Config.path_to_file = 'features.rb'
78
78
  FeatureFlipper::Config.reload_config
79
- FeatureFlipper.reset_current_feature_groups
79
+ FeatureFlipper.reset_active_feature_groups
80
80
  end
81
81
 
82
82
  test 'should show a beta feature to the feature group' do
83
83
  Rails.stubs(:env).returns('production')
84
- FeatureFlipper.current_feature_groups << :beta_users
84
+ FeatureFlipper.active_feature_groups << :beta_users
85
85
 
86
86
  assert show_feature?(:beta_feature_old)
87
87
  assert show_feature?(:beta_feature_new)
@@ -89,7 +89,7 @@ context 'dynamic feature groups' do
89
89
 
90
90
  test 'should not show a beta feature if not in the group' do
91
91
  Rails.stubs(:env).returns('production')
92
- FeatureFlipper.current_feature_groups << :different_feature_group
92
+ FeatureFlipper.active_feature_groups << :different_feature_group
93
93
 
94
94
  assert !show_feature?(:beta_feature_old)
95
95
  assert !show_feature?(:beta_feature_new)
@@ -97,7 +97,7 @@ context 'dynamic feature groups' do
97
97
 
98
98
  test 'should always show a beta feature on dev' do
99
99
  Rails.stubs(:env).returns('development')
100
- FeatureFlipper.current_feature_groups << nil
100
+ FeatureFlipper.active_feature_groups << nil
101
101
 
102
102
  assert show_feature?(:beta_feature_old)
103
103
  assert show_feature?(:beta_feature_new)
@@ -105,8 +105,8 @@ context 'dynamic feature groups' do
105
105
 
106
106
  test 'can be in two feature groups at the same time' do
107
107
  Rails.stubs(:env).returns('production')
108
- FeatureFlipper.current_feature_groups << :beta_users
109
- FeatureFlipper.current_feature_groups << :employees
108
+ FeatureFlipper.active_feature_groups << :beta_users
109
+ FeatureFlipper.active_feature_groups << :employees
110
110
 
111
111
  assert show_feature?(:beta_feature_new)
112
112
  assert show_feature?(:employee_feature)
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 1.1.0
9
+ version: 1.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Florian Munz
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-21 00:00:00 +02:00
17
+ date: 2010-06-01 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies: []
20
20