feature_flipper 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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