pinball_wizard 0.0.1.pre → 0.3.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.
- checksums.yaml +5 -13
- data/.gitignore +9 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +32 -0
- data/LICENSE +21 -0
- data/README.md +336 -0
- data/Rakefile +4 -0
- data/bower.json +14 -0
- data/dist/css_tagger.js +42 -0
- data/dist/css_tagger.min.js +3 -0
- data/dist/pinball_wizard.js +227 -0
- data/gulpfile.js +40 -0
- data/karma.conf.js +66 -0
- data/lib/pinball_wizard.rb +5 -0
- data/lib/pinball_wizard/configuration.rb +17 -0
- data/lib/pinball_wizard/dsl.rb +38 -0
- data/lib/pinball_wizard/feature.rb +52 -0
- data/lib/pinball_wizard/helpers/hash.rb +26 -0
- data/lib/pinball_wizard/null_feature.rb +7 -0
- data/lib/pinball_wizard/railtie.rb +9 -0
- data/lib/pinball_wizard/registry.rb +44 -0
- data/lib/pinball_wizard/version.rb +3 -0
- data/lib/pinball_wizard/view_helpers/rails.rb +13 -0
- data/lib/pinball_wizard/view_helpers/sinatra/slim.rb +15 -0
- data/package.json +45 -0
- data/pinball_wizard.gemspec +20 -0
- data/spec/pinball_wizard/dsl_spec.rb +73 -0
- data/spec/pinball_wizard/feature_spec.rb +89 -0
- data/spec/pinball_wizard/registry_spec.rb +56 -0
- data/src/css_tagger.coffee +44 -0
- data/src/pinball_wizard.coffee +157 -0
- data/test/spec/css_tagger_spec.coffee +50 -0
- data/test/spec/pinball_wizard_spec.coffee +268 -0
- data/test/test-main.coffee +25 -0
- metadata +47 -10
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YzI0NGQwYzQyZTIzZTdiY2NmNzg5YTdhYTQ4MDdkMWEwODQ4MTA5YQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 42cbebb8dd5c1c26041835f0bf8149703670e028
|
4
|
+
data.tar.gz: d9222cff9a8711eaf7a1423ecc4f5a52cc383b6f
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ODM1NzU5NjQ2ZmY1OWUwOTFmYzZmMTFiMGMyY2YzNGMzOTE5OTg4YzBkYmYz
|
11
|
-
NmNhOTQ4ZDZhOTM0ZTAwNzZiMTE4NjY0ZWQ0Zjg4NDk3MWUzN2U=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MDMxNjE2ZjdhNmExYzJkNDI2MDQ1NDZjYzhhMDYxYzQ5Mzc1MjZmMDNlNjdk
|
14
|
-
ZDhlZWVlZjVlYzI5ZTVmNWJlMzNjMGQzYmU2ZTljNjRhNDAyZDc4NzZkMjY2
|
15
|
-
MmU1MDMxNjljNjBlZGFiYTEzMWE1NzUxZTRmZGE4ZGU1ZDM2MmQ=
|
6
|
+
metadata.gz: 473cb966be4e5ef8151fec9a9a8b49c76a810593f235478a3a69435f5c2ff4825490bff06d573aaf96ff2664ac94867536d8f147f5f7f46de106f4980b107881
|
7
|
+
data.tar.gz: e910016832eb2bb49ffc292b6e2be0c308800fbf1c46a7371c2ba2c13182d6ae61bebad9a0978d10e7ae233fefb90e97ce1e5077ec0d11b723842348a54081ae
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# v0.3.0
|
2
|
+
* [feature] Automatically add and remove CSS class `.use-{feature-name}` to `<html>` as features are enabled and disabled.
|
3
|
+
* [feature] Switch to karma for the test runner.
|
4
|
+
* [deprecated] Removed `?pinball_feature_name` query param
|
5
|
+
|
6
|
+
[Compare v0.2.0..v0.3.0](https://github.com/primedia/pinball_wizard/compare/v0.2.0...v0.3.0)
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
coderay (1.1.0)
|
5
|
+
diff-lcs (1.2.5)
|
6
|
+
method_source (0.8.2)
|
7
|
+
pry (0.10.0)
|
8
|
+
coderay (~> 1.1.0)
|
9
|
+
method_source (~> 0.8.1)
|
10
|
+
slop (~> 3.4)
|
11
|
+
rake (10.3.2)
|
12
|
+
rspec (3.0.0)
|
13
|
+
rspec-core (~> 3.0.0)
|
14
|
+
rspec-expectations (~> 3.0.0)
|
15
|
+
rspec-mocks (~> 3.0.0)
|
16
|
+
rspec-core (3.0.1)
|
17
|
+
rspec-support (~> 3.0.0)
|
18
|
+
rspec-expectations (3.0.1)
|
19
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
20
|
+
rspec-support (~> 3.0.0)
|
21
|
+
rspec-mocks (3.0.1)
|
22
|
+
rspec-support (~> 3.0.0)
|
23
|
+
rspec-support (3.0.0)
|
24
|
+
slop (3.5.0)
|
25
|
+
|
26
|
+
PLATFORMS
|
27
|
+
ruby
|
28
|
+
|
29
|
+
DEPENDENCIES
|
30
|
+
pry
|
31
|
+
rake
|
32
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2014 RentPath, Inc. http://rentpath.com
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,336 @@
|
|
1
|
+
# Client and Server Feature Flipping
|
2
|
+
|
3
|
+
<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Pinball_Flippers_-_Demolition_Man.JPG/1024px-Pinball_Flippers_-_Demolition_Man.JPG" width="100%">
|
4
|
+
|
5
|
+
[<img src="http://img.youtube.com/vi/DthtDjhqVOU/1.jpg" height="40"> The Who & Elton John - Pinball Wizard (Tommy 1975)](https://www.youtube.com/watch?v=DthtDjhqVOU)
|
6
|
+
|
7
|
+
`PinballWizard` brings feature flipping into a simple and uniform API in both client-side JavaScript and Ruby.
|
8
|
+
|
9
|
+
## Why?
|
10
|
+
|
11
|
+
PinballWizard is intended to work with heavily cached pages (e.g. Varnish) that need feature flipping. It works well with third parties such as [Optimizely](http://optimizely.com/) where flipping occurs after HTML is rendered.
|
12
|
+
|
13
|
+
## What is a *feature*?
|
14
|
+
|
15
|
+
A set of Ruby, HTML, JavaScript, and CSS that can be turned on or off.
|
16
|
+
|
17
|
+
A feature is simply a name and default state:
|
18
|
+
|
19
|
+
* *active*: If it is currently turned on and running.
|
20
|
+
* *inactive*: Not turned on.
|
21
|
+
* *disabled*: Not turned on and cannot be activated.
|
22
|
+
|
23
|
+
|
24
|
+
## Building
|
25
|
+
1. Define and register the feature in the [Ruby app](#ruby).
|
26
|
+
2. Build the [JavaScript component](#javascript).
|
27
|
+
3. Write the corresponding [HTML](#html) and [CSS](#css)
|
28
|
+
4. [Activate and test your feature](#activating-and-testing-features).
|
29
|
+
|
30
|
+
## Ruby
|
31
|
+
|
32
|
+
Define your feature in (typically `config/initializers/pinball_wizard.rb`).
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
PinballWizard::DSL.build do
|
36
|
+
# Active when the page loads:
|
37
|
+
feature :example, active: true
|
38
|
+
|
39
|
+
# Deactive when the page loads:
|
40
|
+
feature :example, active: false
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
You can also pass in a proc for situtations where active/inactive is conditional. Returning false with make the feature inactive.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
PinballWizard::DSL.build do
|
48
|
+
feature :example, active: proc { }
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
## HTML
|
53
|
+
|
54
|
+
Once the feature is registered, you can use Slim to include the HTML partial found at `app/views/features/example.slim`. This is only included if the feature is available, which allows the HTML to stay small.
|
55
|
+
|
56
|
+
```slim
|
57
|
+
= feature 'example'
|
58
|
+
```
|
59
|
+
|
60
|
+
To use a different partial for the same feature, pass in the `partial:` key. This will use `app/views/features/example_button.slim`.
|
61
|
+
|
62
|
+
If the feature is not active immediately, it's recommended to hide the HTML with inline or external CSS.
|
63
|
+
|
64
|
+
```slim
|
65
|
+
= feature 'example', partial: :example_button'
|
66
|
+
```
|
67
|
+
|
68
|
+
## CSS
|
69
|
+
|
70
|
+
PinballWizard automatically adds and removes a CSS class named `.use-{feature-name}` to the `<html>` tag. This allows you to write CSS when features are active.
|
71
|
+
|
72
|
+
It is also recommended to organize your CSS similar to Ruby:
|
73
|
+
|
74
|
+
```scss
|
75
|
+
// app/assets/stylesheets/features/_example.scss
|
76
|
+
|
77
|
+
.use-example {
|
78
|
+
// CSS when the 'example' feature is active.
|
79
|
+
}
|
80
|
+
```
|
81
|
+
|
82
|
+
Then include it on the main file with `@import 'features/example'`
|
83
|
+
|
84
|
+
|
85
|
+
## JavaScript
|
86
|
+
|
87
|
+
Features subscribe to events and respond when they're activated or deactivated. It no longer needs to know about Optimizely, cookies, or url params. (Single Responsibility Principle FTW)
|
88
|
+
|
89
|
+
One advantage to this approach is that you can activate features after the DOM is loaded (for testing).
|
90
|
+
|
91
|
+
When pinball runs, it will automatically activate the features.
|
92
|
+
|
93
|
+
### Example AMD/RequireJS Module
|
94
|
+
|
95
|
+
```coffee
|
96
|
+
define ['pinball_wizard'], (pinball) ->
|
97
|
+
|
98
|
+
# Define feature component functions here ...
|
99
|
+
|
100
|
+
pinball.subscribe 'example',
|
101
|
+
->
|
102
|
+
# callback when activated. e.g. show it
|
103
|
+
->
|
104
|
+
# callback when deactivated. e.g. hide it.
|
105
|
+
|
106
|
+
# Return component functions to expose.
|
107
|
+
```
|
108
|
+
|
109
|
+
### Example Flight Component
|
110
|
+
|
111
|
+
```coffee
|
112
|
+
define ['pinball_wizard'], (pinball) ->
|
113
|
+
|
114
|
+
@after 'initialize', ->
|
115
|
+
pinball.subscribe 'example',
|
116
|
+
=>
|
117
|
+
# callback when activated. e.g. show it
|
118
|
+
=>
|
119
|
+
# callback when deactivated. e.g. hide it.
|
120
|
+
|
121
|
+
```
|
122
|
+
|
123
|
+
### Asking *(pseudo-code)*
|
124
|
+
|
125
|
+
As an alternative, a feature may check if it's active. This method is not preferred since it only occurs once during page load.
|
126
|
+
|
127
|
+
```coffee
|
128
|
+
define ['pinball_wizard'], (pinball) ->
|
129
|
+
|
130
|
+
if pinball.isActive('example')
|
131
|
+
# Do something
|
132
|
+
```
|
133
|
+
|
134
|
+
## Activating and Testing Features
|
135
|
+
|
136
|
+
### With a URL Param
|
137
|
+
Add `pinball` to the URL (e.g. `?pinball=example_a,example_b`).
|
138
|
+
|
139
|
+
### Post-Render (after page load)
|
140
|
+
|
141
|
+
```javascript
|
142
|
+
pinball.activate('example');
|
143
|
+
```
|
144
|
+
|
145
|
+
```javascript
|
146
|
+
pinball.deactivate('example');
|
147
|
+
```
|
148
|
+
|
149
|
+
Activating a feature that is already active or disabled will have no effect.
|
150
|
+
|
151
|
+
#### Optionally Supply a Source
|
152
|
+
|
153
|
+
Add an optional source as a second argument to help know where features are
|
154
|
+
activated while debugging.
|
155
|
+
|
156
|
+
```javascript
|
157
|
+
pinball.activate('example','source name');
|
158
|
+
```
|
159
|
+
|
160
|
+
|
161
|
+
## JsConfig
|
162
|
+
The application keeps a list of features and passes them in the JsConfig object (e.g. `window.ApartmentGuide`). These define what's available and activated on page load. AG is hooked up to PinballWizard to automatically be aware of these. No additional code is necessary.
|
163
|
+
|
164
|
+
`{ "feature_name": "state", "feature_name": "state" }`
|
165
|
+
|
166
|
+
e.g. `{ "feature_a": "active", "feature_b": "inactive", "feature_c": "disabled" }`
|
167
|
+
|
168
|
+
## Debugging
|
169
|
+
|
170
|
+
Add it to the url:
|
171
|
+
`?pinball=debug`
|
172
|
+
|
173
|
+
Turn on logging in JavaScript:
|
174
|
+
```js
|
175
|
+
pinball.debug();
|
176
|
+
```
|
177
|
+
|
178
|
+
Show current state in the JavaScript console:
|
179
|
+
```js
|
180
|
+
pinball.state();
|
181
|
+
```
|
182
|
+
|
183
|
+
## Integrations
|
184
|
+
* [Rails](https://github.com/primedia/pinball_wizard/wiki/Integrating-with-Rails)
|
185
|
+
* [Sinatra with Slim](https://github.com/primedia/pinball_wizard/wiki/Integrating-with-Sinatra)
|
186
|
+
* [Optimizely](https://github.com/primedia/pinball_wizard/wiki/Integrating-a-Feature-with-Optimizely)
|
187
|
+
|
188
|
+
For RentPath specific functionality, including ConFusion, see [pinball_wizard-rentpath](https://github.com/primedia/pinball_wizard-rentpath)
|
189
|
+
|
190
|
+
## Extra: Custom Ruby Class
|
191
|
+
|
192
|
+
By default, features are instances of `PinballWizard::Feature`. You can define your own class and register it according to a hash key. This is useful to disable features.
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
# e.g. app/features/my_feature.rb
|
196
|
+
module PinballWizard
|
197
|
+
class MyFeature < Feature
|
198
|
+
def determine_state
|
199
|
+
if my_condition?
|
200
|
+
disable "My Feature: My Reason"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# e.g. config/initializers/pinball_wizard.rb
|
207
|
+
PinballWizard.configure do |c|
|
208
|
+
c.class_patterns = my_option: PinballWizard::MyFeature
|
209
|
+
end
|
210
|
+
|
211
|
+
# e.g. config/features.rb
|
212
|
+
PinballWizard::DSL.build do
|
213
|
+
feature :example, :my_option
|
214
|
+
end
|
215
|
+
```
|
216
|
+
|
217
|
+
## Getting started for development.
|
218
|
+
```
|
219
|
+
git checkout dev
|
220
|
+
git pull origin dev
|
221
|
+
git checkout -b my_branch
|
222
|
+
npm run preversion
|
223
|
+
```
|
224
|
+
|
225
|
+
## A basic red-green-refactor workflow.
|
226
|
+
|
227
|
+
```
|
228
|
+
npm install
|
229
|
+
npm run watch
|
230
|
+
npm run watch:test # in another terminal window or pane
|
231
|
+
```
|
232
|
+
|
233
|
+
## Examples of common tasks.
|
234
|
+
|
235
|
+
npm script commands are defined in the scripts section of package.json.
|
236
|
+
To see a full list of available npm commands, run:
|
237
|
+
|
238
|
+
```
|
239
|
+
npm run
|
240
|
+
```
|
241
|
+
|
242
|
+
### Install NPM Dependencies
|
243
|
+
|
244
|
+
```
|
245
|
+
npm install
|
246
|
+
```
|
247
|
+
|
248
|
+
### One-time compile of application source and tests.
|
249
|
+
|
250
|
+
```
|
251
|
+
npm run compile
|
252
|
+
```
|
253
|
+
|
254
|
+
### Compile application source & tests and build the distribution as files change.
|
255
|
+
|
256
|
+
```
|
257
|
+
npm run watch
|
258
|
+
```
|
259
|
+
|
260
|
+
### Running Tests.
|
261
|
+
|
262
|
+
One time.
|
263
|
+
|
264
|
+
```
|
265
|
+
npm test
|
266
|
+
```
|
267
|
+
|
268
|
+
Watch continuously and run tests when code or specs change.
|
269
|
+
|
270
|
+
```
|
271
|
+
npm run watch:test
|
272
|
+
```
|
273
|
+
|
274
|
+
### Cleaning
|
275
|
+
|
276
|
+
Remove compiled code and tests in .tmp/.
|
277
|
+
|
278
|
+
```
|
279
|
+
npm run clean
|
280
|
+
```
|
281
|
+
|
282
|
+
Remove compiled code and tests, `node_modules`
|
283
|
+
|
284
|
+
```
|
285
|
+
npm run clean:all
|
286
|
+
```
|
287
|
+
|
288
|
+
Remove compiled code, tests, `node_modules`; reinstall
|
289
|
+
node modules; recompile code and tests.
|
290
|
+
|
291
|
+
```
|
292
|
+
npm run reset
|
293
|
+
```
|
294
|
+
|
295
|
+
### Building a Distribution
|
296
|
+
|
297
|
+
To build a distribution and tag it, run one of the following commands.
|
298
|
+
|
299
|
+
```
|
300
|
+
npm version patch -m "Bumped to %s"
|
301
|
+
npm version minor -m "Bumped to %s"
|
302
|
+
npm version major -m "Bumped to %s"
|
303
|
+
```
|
304
|
+
|
305
|
+
There's a 'preversion' script in package.json that does the following:
|
306
|
+
- Remove the .tmp/ directory.
|
307
|
+
- Remove the node_modules directories.
|
308
|
+
- Install all npm packages.
|
309
|
+
- Compile the application source and specs.
|
310
|
+
- Run the tests.
|
311
|
+
- Rebuild the distribution.
|
312
|
+
|
313
|
+
Just build a distribution.
|
314
|
+
|
315
|
+
```
|
316
|
+
npm run build
|
317
|
+
```
|
318
|
+
|
319
|
+
## Notes
|
320
|
+
- The `dist/` directory must be part of the repo - don't gitignore it!
|
321
|
+
|
322
|
+
|
323
|
+
## Contributing
|
324
|
+
|
325
|
+
Fork and submit a pull request. This is a [README driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) process, please contribute by modifying this document.
|
326
|
+
|
327
|
+
|
328
|
+
## Credits
|
329
|
+
|
330
|
+
- Pinball photo:
|
331
|
+
- [ElHeineken](http://commons.wikimedia.org/wiki/User:ElHeineken)
|
332
|
+
- http://creativecommons.org/licenses/by/3.0/
|
333
|
+
|
334
|
+
## License
|
335
|
+
|
336
|
+
[MIT](https://github.com/primedia/pinball_wizard/blob/master/LICENSE)
|
data/Rakefile
ADDED