flip 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
  gemspec
data/README.md CHANGED
@@ -1,21 +1,29 @@
1
1
  Flip — flip your features
2
2
  ================
3
3
 
4
- [Learnable](https://learnable.com) uses feature flippers ([so does Flickr](http://code.flickr.com/blog/2009/12/02/flipping-out/)) as a tool to help achieve [continuous deployment](http://timothyfitz.wordpress.com/2009/02/10/continuous-deployment-at-imvu-doing-the-impossible-fifty-times-a-day/).
4
+ **Flip** provides a declarative, layered way of enabling and disabling application functionality at run-time.
5
5
 
6
- **Flip** gives us a declarative, layered mechanism to enable and disable features. There's a configurable system-wide default (`default: !Rails.env.production?` works nicely), plus three layers of strategies to determine status per-feature:
6
+ This gem optimizes for:
7
7
 
8
- * The declared default, e.g. `feature :world_domination, default: true`,
9
- * A database-backed strategy, for flipping features site-wide for all users.
10
- * A cookie-backed strategy, for privately previewing features in your own browser only.
8
+ * developer ease-of-use,
9
+ * visibility and control for other stakeholders (like marketing); and
10
+ * run-time performance
11
11
 
12
- (Hint: that last one is a a killer feature..)
12
+ There are three layers of strategies per feature:
13
+
14
+ * default
15
+ * database, to flip features site-wide for all users
16
+ * cookie, to flip features just for you (or someone else)
17
+
18
+ There is also a configurable system-wide default - !Rails.env.production?` works nicely.
19
+
20
+ Flip has a dashboard UI that's easy to understand and use.
21
+
22
+ ![Feature Flipper Dashboard](https://dl.dropbox.com/u/13833591/flip-gem-dashboard.png "Feature Flipper Dashboard")
13
23
 
14
24
  Install
15
25
  -------
16
26
 
17
- Note: the alpha version number indicates Flip is currently being extracted from its host application. **The process described here is currently fictional.** But it does have a happy ending.
18
-
19
27
  **Rails 3.0 and 3.1+**
20
28
 
21
29
  # Gemfile
@@ -27,8 +35,6 @@ Note: the alpha version number indicates Flip is currently being extracted from
27
35
  # Run the migration
28
36
  > rake db:migrate
29
37
 
30
- # They lived happily ever after.
31
-
32
38
 
33
39
  Declaring Features
34
40
  ------------------
@@ -64,7 +70,7 @@ Declaring Features
64
70
  Checking Features
65
71
  -----------------
66
72
 
67
- Feature status can be checked by any code using `on?` or using the dynamic predicate methods:
73
+ `Flip.on?` or the dynamic predicate methods are used to check feature state:
68
74
 
69
75
  Flip.on? :world_domination # true
70
76
  Flip.world_domination? # true
@@ -72,7 +78,7 @@ Feature status can be checked by any code using `on?` or using the dynamic predi
72
78
  Flip.on? :shiny_things # false
73
79
  Flip.shiny_things? # false
74
80
 
75
- Within view and controller methods, the `FlipHelper` module provides a `feature?(key)` method:
81
+ Views and controllers use the `feature?(key)` method:
76
82
 
77
83
  <div>
78
84
  <% if feature? :world_domination %>
@@ -98,15 +104,40 @@ The `Flip::ControllerFilters` module is mixed into the base `ApplicationControll
98
104
 
99
105
  end
100
106
 
101
- Note that conditionally declared routes require a server restart to notice changes to feature flags, so they're not a good idea; database/cookie feature flipping will be ignored.
107
+ Dashboard
108
+ ---------
109
+
110
+ The dashboard provides visibility and control over the features.
111
+
112
+ The gem includes some basic styles:
113
+
114
+ = content_for :stylesheets_head do
115
+ = stylesheet_link_tag "flip"
102
116
 
117
+ You probably don't want the dashboard to be public. Here's one way of implementing access control.
103
118
 
104
- Command Center
105
- --------------
119
+ app/controllers/admin/features_controller.rb:
106
120
 
107
- A dashboard allows you to view the current state of the feature set, and flip any switchable strategies (database, cookie). *Screenshot coming&hellip;*
121
+ class Admin::FeaturesController < Flip::FeaturesController
122
+ before_filter :assert_authenticated_as_admin
123
+ end
124
+
125
+ app/controllers/admin/feature_strategies_controller.rb:
126
+
127
+ class Admin::FeatureStrategiesController < Flip::FeaturesController
128
+ before_filter :assert_authenticated_as_admin
129
+ end
130
+
131
+ routes.rb:
132
+
133
+ namespace :admin do
134
+ resources :features, only: [ :index ] do
135
+ resources :feature_strategies, only: [ :update, :destroy ]
136
+ end
137
+ end
108
138
 
139
+ mount Flip::Engine => "/admin/features"
109
140
 
110
141
  ----
111
- Created by Paul Annesley
112
- Copyright © 2011 Learnable Pty Ltd, [MIT Licence](http://www.opensource.org/licenses/mit-license.php).
142
+ Created by Paul Annesley
143
+ Copyright © 2011-2013 Learnable Pty Ltd, [MIT Licence](http://www.opensource.org/licenses/mit-license.php).
@@ -1,64 +1,70 @@
1
1
  /* Flip */
2
2
 
3
3
  .flip {
4
- margin: 2em 1em 4em 1em;
4
+ margin: 0;
5
+ }
6
+
7
+ .flip h1 {
8
+ color:#666666;
9
+ font-size: 229%;
10
+ line-height: 44.928px;
11
+ margin: 13.5px 0;
5
12
  }
6
13
 
7
14
  .flip th.name, .flip th.description, .flip th.status {
8
- visibility: hidden;
15
+ visibility: hidden;
9
16
  }
10
17
 
11
18
  .flip td.name {
12
- font-family: Monaco, sans-serif;
13
- font-weight: bold;
19
+ font-family: Monaco, sans-serif;
20
+ font-weight: bold;
14
21
  }
15
22
 
16
23
  .flip td.name, .flip td.description {
17
- vertical-align: top;
24
+ vertical-align: top;
18
25
  }
19
26
 
20
27
  .flip th {
21
- font-weight: normal;
22
- text-align: left;
23
- vertical-align: top;
28
+ font-weight: normal;
29
+ text-align: left;
30
+ vertical-align: top;
24
31
  }
25
32
 
26
33
  .flip th .description {
27
- font-weight: normal;
28
- display: block;
29
- font-size: 80%;
34
+ font-weight: normal;
35
+ display: block;
36
+ font-size: 80%;
30
37
  }
31
38
 
32
39
  .flip th, .flip td {
33
- padding: 5px 10px;
34
- width: 160px;
35
- height: 40px;
40
+ padding: 5px 10px;
41
+ width: 160px;
42
+ height: 40px;
36
43
  }
37
44
 
38
45
  .flip td.off, .flip td.on, .flip td.pass {
39
- text-align: center;
40
- text-transform: capitalize;
46
+ text-align: center;
47
+ text-transform: capitalize;
41
48
  }
42
49
 
43
50
  .flip td.off {
44
- background-color: #fbb;
51
+ background-color: #fbb;
45
52
  }
46
53
 
47
54
  .flip td.on {
48
- background-color: #cfc;
55
+ background-color: #cfc;
49
56
  }
50
57
 
51
58
  .flip td.pass {
52
- background-color: #eef;
59
+ background-color: #eef;
53
60
  }
54
61
 
55
62
  .flip form {
56
- display: inline;
63
+ display: inline;
57
64
  }
58
65
 
59
66
  .flip form input[type=submit] {
60
- font-size: 80%;
61
- padding: 2px 5px;
62
- margin: 0;
67
+ font-size: 80%;
68
+ padding: 2px 5px;
69
+ margin: 0;
63
70
  }
64
-
@@ -1,60 +1,62 @@
1
- <h1>Feature Flippers</h1>
2
-
3
- <table class="flip">
4
- <thead>
5
- <th class="name">Feature Name</th>
6
- <th class="description">Description</th>
7
- <th class="status">Status</th>
8
- <% @p.strategies.each do |strategy| %>
1
+ <div class="flip">
2
+ <h1>Feature Flippers</h1>
3
+
4
+ <table>
5
+ <thead>
6
+ <th class="name">Feature Name</th>
7
+ <th class="description">Description</th>
8
+ <th class="status">Status</th>
9
+ <% @p.strategies.each do |strategy| %>
10
+ <th>
11
+ <%= strategy.name %>
12
+ <span class="description"><%= strategy.description %></span>
13
+ </th>
14
+ <% end %>
9
15
  <th>
10
- <%= strategy.name %>
11
- <span class="description"><%= strategy.description %></span>
16
+ Default
17
+ <span class="description">The system default when no strategies match.</span>
12
18
  </th>
13
- <% end %>
14
- <th>
15
- Default
16
- <span class="description">The system default when no strategies match.</span>
17
- </th>
18
- </thead>
19
- <tbody>
20
- <% @p.definitions.each do |definition| %>
21
- <tr>
22
- <td class="name"><%= definition.name %></td>
23
-
24
- <td class="description"><%= definition.description %></td>
25
-
26
- <%= content_tag :td, class: @p.status(definition) do %>
27
- <%= @p.status definition %>
28
- <% end %>
19
+ </thead>
20
+ <tbody>
21
+ <% @p.definitions.each do |definition| %>
22
+ <tr>
23
+ <td class="name"><%= definition.name %></td>
29
24
 
30
- <% @p.strategies.each do |strategy| %>
31
- <%= content_tag :td, class: @p.strategy_status(strategy, definition) || "pass" do %>
32
- <%= @p.strategy_status strategy, definition %>
25
+ <td class="description"><%= definition.description %></td>
26
+
27
+ <%= content_tag :td, class: @p.status(definition) do %>
28
+ <%= @p.status definition %>
29
+ <% end %>
33
30
 
34
- <% if strategy.switchable? %>
35
- <%= form_tag(@p.switch_url(strategy, definition), method: :put) do %>
36
- <% unless @p.strategy_status(strategy, definition) == "on" %>
37
- <%= submit_tag "Switch On" %>
31
+ <% @p.strategies.each do |strategy| %>
32
+ <%= content_tag :td, class: @p.strategy_status(strategy, definition) || "pass" do %>
33
+ <%= @p.strategy_status strategy, definition %>
34
+
35
+ <% if strategy.switchable? %>
36
+ <%= form_tag(@p.switch_url(strategy, definition), method: :put) do %>
37
+ <% unless @p.strategy_status(strategy, definition) == "on" %>
38
+ <%= submit_tag "Switch On" %>
39
+ <% end %>
40
+ <% unless @p.strategy_status(strategy, definition) == "off" %>
41
+ <%= submit_tag "Switch Off" %>
42
+ <% end %>
38
43
  <% end %>
39
- <% unless @p.strategy_status(strategy, definition) == "off" %>
40
- <%= submit_tag "Switch Off" %>
44
+ <% unless @p.strategy_status(strategy, definition).blank? %>
45
+ <%= form_tag(@p.switch_url(strategy, definition), method: :delete) do %>
46
+ <%= submit_tag "Delete" %>
47
+ <% end %>
41
48
  <% end %>
42
49
  <% end %>
43
- <% unless @p.strategy_status(strategy, definition).blank? %>
44
- <%= form_tag(@p.switch_url(strategy, definition), method: :delete) do %>
45
- <%= submit_tag "Delete" %>
46
- <% end %>
47
- <% end %>
48
- <% end %>
49
50
 
51
+ <% end %>
50
52
  <% end %>
51
- <% end %>
52
53
 
53
- <%= content_tag :td, class: @p.default_status(definition) do %>
54
- <%= @p.default_status definition %>
55
- <% end %>
54
+ <%= content_tag :td, class: @p.default_status(definition) do %>
55
+ <%= @p.default_status definition %>
56
+ <% end %>
56
57
 
57
- </tr>
58
- <% end %>
59
- </tbody>
60
- </table>
58
+ </tr>
59
+ <% end %>
60
+ </tbody>
61
+ </table>
62
+ </div>
data/lib/flip/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Flip
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,52 +9,72 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-04 00:00:00.000000000 Z
12
+ date: 2013-02-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70160385209800 !ruby/object:Gem::Requirement
17
- none: false
16
+ prerelease: false
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
21
  version: '3.0'
22
+ none: false
22
23
  type: :runtime
23
- prerelease: false
24
- version_requirements: *70160385209800
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '3.0'
29
+ none: false
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: i18n
27
- requirement: &70160385207660 !ruby/object:Gem::Requirement
28
- none: false
32
+ prerelease: false
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  requirements:
30
35
  - - ! '>='
31
36
  - !ruby/object:Gem::Version
32
37
  version: '0'
38
+ none: false
33
39
  type: :runtime
34
- prerelease: false
35
- version_requirements: *70160385207660
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ none: false
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rspec
38
- requirement: &70160380032000 !ruby/object:Gem::Requirement
39
- none: false
48
+ prerelease: false
49
+ requirement: !ruby/object:Gem::Requirement
40
50
  requirements:
41
51
  - - ~>
42
52
  - !ruby/object:Gem::Version
43
53
  version: '2.5'
54
+ none: false
44
55
  type: :development
45
- prerelease: false
46
- version_requirements: *70160380032000
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '2.5'
61
+ none: false
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rake
49
- requirement: &70160380031580 !ruby/object:Gem::Requirement
50
- none: false
64
+ prerelease: false
65
+ requirement: !ruby/object:Gem::Requirement
51
66
  requirements:
52
67
  - - ! '>='
53
68
  - !ruby/object:Gem::Version
54
69
  version: '0'
70
+ none: false
55
71
  type: :development
56
- prerelease: false
57
- version_requirements: *70160380031580
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ none: false
58
78
  description: Declarative API for specifying features, switchable in declaration, database
59
79
  and cookies.
60
80
  email:
@@ -114,20 +134,20 @@ rdoc_options: []
114
134
  require_paths:
115
135
  - lib
116
136
  required_ruby_version: !ruby/object:Gem::Requirement
117
- none: false
118
137
  requirements:
119
138
  - - ! '>='
120
139
  - !ruby/object:Gem::Version
121
140
  version: '0'
122
- required_rubygems_version: !ruby/object:Gem::Requirement
123
141
  none: false
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
143
  requirements:
125
144
  - - ! '>='
126
145
  - !ruby/object:Gem::Version
127
146
  version: '0'
147
+ none: false
128
148
  requirements: []
129
149
  rubyforge_project: flip
130
- rubygems_version: 1.8.11
150
+ rubygems_version: 1.8.23
131
151
  signing_key:
132
152
  specification_version: 3
133
153
  summary: A feature flipper for Rails web applications.
@@ -142,3 +162,4 @@ test_files:
142
162
  - spec/feature_set_spec.rb
143
163
  - spec/flip_spec.rb
144
164
  - spec/spec_helper.rb
165
+ has_rdoc: