flip_fab 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +5 -0
  3. data/Gemfile +16 -0
  4. data/Gemfile.lock +92 -0
  5. data/LICENSE.txt +9 -0
  6. data/README.md +168 -0
  7. data/example/rails_app/.gitignore +17 -0
  8. data/example/rails_app/Gemfile +36 -0
  9. data/example/rails_app/Gemfile.lock +178 -0
  10. data/example/rails_app/README.rdoc +28 -0
  11. data/example/rails_app/Rakefile +6 -0
  12. data/example/rails_app/app/assets/images/.keep +0 -0
  13. data/example/rails_app/app/assets/images/justin_beaver.jpg +0 -0
  14. data/example/rails_app/app/assets/images/regular_beaver.jpg +0 -0
  15. data/example/rails_app/app/assets/javascripts/application.js +16 -0
  16. data/example/rails_app/app/assets/javascripts/beavers.js.coffee +3 -0
  17. data/example/rails_app/app/assets/stylesheets/application.css +15 -0
  18. data/example/rails_app/app/assets/stylesheets/beavers.css.scss +3 -0
  19. data/example/rails_app/app/assets/stylesheets/scaffolds.css.scss +69 -0
  20. data/example/rails_app/app/controllers/application_controller.rb +5 -0
  21. data/example/rails_app/app/controllers/beavers_controller.rb +74 -0
  22. data/example/rails_app/app/controllers/concerns/.keep +0 -0
  23. data/example/rails_app/app/helpers/application_helper.rb +2 -0
  24. data/example/rails_app/app/helpers/beavers_helper.rb +2 -0
  25. data/example/rails_app/app/mailers/.keep +0 -0
  26. data/example/rails_app/app/models/.keep +0 -0
  27. data/example/rails_app/app/models/beaver.rb +2 -0
  28. data/example/rails_app/app/models/concerns/.keep +0 -0
  29. data/example/rails_app/app/views/beavers/_form.html.erb +21 -0
  30. data/example/rails_app/app/views/beavers/edit.html.erb +6 -0
  31. data/example/rails_app/app/views/beavers/index.html.erb +25 -0
  32. data/example/rails_app/app/views/beavers/index.json.jbuilder +4 -0
  33. data/example/rails_app/app/views/beavers/new.html.erb +5 -0
  34. data/example/rails_app/app/views/beavers/show.html.erb +9 -0
  35. data/example/rails_app/app/views/beavers/show.json.jbuilder +1 -0
  36. data/example/rails_app/app/views/layouts/application.html.erb +18 -0
  37. data/example/rails_app/bin/bundle +3 -0
  38. data/example/rails_app/bin/rails +4 -0
  39. data/example/rails_app/bin/rake +4 -0
  40. data/example/rails_app/config/application.rb +25 -0
  41. data/example/rails_app/config/boot.rb +4 -0
  42. data/example/rails_app/config/database.yml +22 -0
  43. data/example/rails_app/config/environment.rb +5 -0
  44. data/example/rails_app/config/environments/development.rb +83 -0
  45. data/example/rails_app/config/environments/test.rb +41 -0
  46. data/example/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  47. data/example/rails_app/config/initializers/cookies_serializer.rb +3 -0
  48. data/example/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  49. data/example/rails_app/config/initializers/flip_fab.rb +1 -0
  50. data/example/rails_app/config/initializers/inflections.rb +16 -0
  51. data/example/rails_app/config/initializers/mime_types.rb +4 -0
  52. data/example/rails_app/config/initializers/session_store.rb +3 -0
  53. data/example/rails_app/config/initializers/wrap_parameters.rb +14 -0
  54. data/example/rails_app/config/locales/en.yml +23 -0
  55. data/example/rails_app/config/rabbit_feed.yml +8 -0
  56. data/example/rails_app/config/routes.rb +58 -0
  57. data/example/rails_app/config/secrets.yml +18 -0
  58. data/example/rails_app/config/unicorn.rb +4 -0
  59. data/example/rails_app/config.ru +4 -0
  60. data/example/rails_app/db/migrate/20140424102400_create_beavers.rb +9 -0
  61. data/example/rails_app/db/schema.rb +22 -0
  62. data/example/rails_app/db/seeds.rb +7 -0
  63. data/example/rails_app/lib/assets/.keep +0 -0
  64. data/example/rails_app/lib/tasks/.keep +0 -0
  65. data/example/rails_app/log/.keep +0 -0
  66. data/example/rails_app/public/404.html +67 -0
  67. data/example/rails_app/public/422.html +67 -0
  68. data/example/rails_app/public/500.html +66 -0
  69. data/example/rails_app/public/favicon.ico +0 -0
  70. data/example/rails_app/public/robots.txt +5 -0
  71. data/example/rails_app/spec/rails_helper.rb +50 -0
  72. data/example/rails_app/spec/spec_helper.rb +8 -0
  73. data/example/rails_app/test/controllers/.keep +0 -0
  74. data/example/rails_app/test/controllers/beavers_controller_test.rb +49 -0
  75. data/example/rails_app/test/fixtures/.keep +0 -0
  76. data/example/rails_app/test/fixtures/beavers.yml +7 -0
  77. data/example/rails_app/test/helpers/.keep +0 -0
  78. data/example/rails_app/test/helpers/beavers_helper_test.rb +4 -0
  79. data/example/rails_app/test/integration/.keep +0 -0
  80. data/example/rails_app/test/mailers/.keep +0 -0
  81. data/example/rails_app/test/models/.keep +0 -0
  82. data/example/rails_app/test/models/beaver_test.rb +7 -0
  83. data/example/rails_app/test/test_helper.rb +13 -0
  84. data/flip_fab.gemspec +20 -0
  85. data/lib/flip_fab/contextual_feature.rb +83 -0
  86. data/lib/flip_fab/cookie_persistence.rb +52 -0
  87. data/lib/flip_fab/feature.rb +24 -0
  88. data/lib/flip_fab/features_by_name.rb +22 -0
  89. data/lib/flip_fab/helper.rb +8 -0
  90. data/lib/flip_fab/persistence.rb +19 -0
  91. data/lib/flip_fab/version.rb +3 -0
  92. data/lib/flip_fab.rb +24 -0
  93. data/spec/lib/flip_fab/contextual_feature_spec.rb +352 -0
  94. data/spec/lib/flip_fab/cookie_persistence.feature +50 -0
  95. data/spec/lib/flip_fab/cookie_persistence_spec.rb +90 -0
  96. data/spec/lib/flip_fab/feature_spec.rb +86 -0
  97. data/spec/lib/flip_fab/features_by_name_spec.rb +34 -0
  98. data/spec/lib/flip_fab/helper.feature +31 -0
  99. data/spec/lib/flip_fab/helper_spec.rb +90 -0
  100. data/spec/lib/flip_fab/persistence_spec.rb +32 -0
  101. data/spec/lib/flip_fab.feature +10 -0
  102. data/spec/lib/flip_fab_spec.rb +47 -0
  103. data/spec/spec_helper.rb +93 -0
  104. data/spec/support/test_app.rb +16 -0
  105. data/spec/support/test_context.rb +10 -0
  106. data/spec/support/test_multiple_persistence.rb +14 -0
  107. data/spec/support/test_persistence.rb +14 -0
  108. data/spec/support/test_rack_context.rb +15 -0
  109. metadata +168 -0
@@ -0,0 +1,90 @@
1
+ require 'rack/test'
2
+
3
+ module FlipFab
4
+ describe Helper do
5
+ include Rack::Test::Methods
6
+ let(:app) { TestApp.new }
7
+ after { FlipFab.features.clear }
8
+
9
+ it 'runs the feature' do
10
+ feature
11
+ end
12
+
13
+ step 'there is a feature with a default state of :default_state' do |default_state|
14
+ FlipFab.define_feature :example_feature, { default: default_state.to_sym, persistence_adapters: [TestPersistence] }
15
+ end
16
+
17
+ step 'there are two contexts' do
18
+ @first_context = TestContext.new
19
+ @second_context = TestContext.new
20
+ end
21
+
22
+ step 'the feature is :expected_state_in_first_context in the first context, :expected_state_in_second_context in the second context' do |expected_state_in_first_context, expected_state_in_second_context|
23
+ expect(@first_context.features[:example_feature].enabled?).to eq(expected_state_in_first_context == 'enabled')
24
+ expect(@second_context.features[:example_feature].enabled?).to eq(expected_state_in_second_context == 'enabled')
25
+ end
26
+
27
+ step 'I :enable_or_disable the feature in the first context' do |enable_or_disable|
28
+ @first_context.features[:example_feature].send(enable_or_disable.to_sym)
29
+ end
30
+
31
+ step 'there is a feature with a default state of :default_state with cookie persistence' do |default_state|
32
+ FlipFab.define_feature :example_feature, { default: default_state.to_sym }
33
+ end
34
+
35
+ step 'I override the state in the URL parameters with :overridden_state' do |overridden_state|
36
+ get "/?example_feature=#{overridden_state}"
37
+ end
38
+
39
+ step 'the feature is :state for the user' do |state|
40
+ expect(app.contextual_features[:example_feature].enabled?).to eq(state=='enabled')
41
+ end
42
+
43
+ step 'I :enable_or_disable the feature for the user' do |enable_or_disable|
44
+ app.contextual_features[:example_feature].send(enable_or_disable.to_sym)
45
+ end
46
+
47
+ describe '#features' do
48
+ let(:params) {{}}
49
+ let(:feature_states) {{ example_feature: :enabled }}
50
+ let(:context) { (TestContext.new feature_states, params) }
51
+ before { FlipFab.define_feature :example_feature, { persistence_adapters: [TestPersistence] } }
52
+ subject { context.features }
53
+
54
+ it 'maps the features to contextual features by feature name' do
55
+ expect(subject[:example_feature]).to be_a ContextualFeature
56
+ end
57
+
58
+ it 'is a FeaturesByName' do
59
+ expect(subject).to be_a FeaturesByName
60
+ end
61
+
62
+ context 'when the feature is overridden in the params' do
63
+ let(:params) {{'example_feature' => 'disabled'}}
64
+
65
+ it 'applies the override to the feature' do
66
+ expect(subject[:example_feature].disabled?).to be_truthy
67
+ end
68
+
69
+ it 'prevents the feature\'s state from being changed' do
70
+ expect{ subject[:example_feature].enable }.not_to change{ subject[:example_feature].enabled? }.from(false)
71
+ end
72
+ end
73
+
74
+ context 'passing the context to the feature' do
75
+
76
+ it 'feature toggling is applied to the context' do
77
+ expect{ subject[:example_feature].disable }.to change{ subject[:example_feature].enabled? }.from(true).to(false)
78
+ end
79
+
80
+ it 'feature toggling is persisted in the context' do
81
+ expect{ subject[:example_feature].disable }.to change{ feature_states }.from({ example_feature: :enabled }).to({ example_feature: :disabled })
82
+ end
83
+ end
84
+
85
+ it 'caches the features' do
86
+ expect(subject).to eq(context.features)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,32 @@
1
+ module FlipFab
2
+ describe Persistence do
3
+ let(:feature_name) { :example_test }
4
+ let(:context) { double(:context) }
5
+ subject { described_class.new feature_name, context }
6
+
7
+ describe '.new' do
8
+
9
+ it 'assigns the feature name' do
10
+ expect(subject.feature_name).to eq(:example_test)
11
+ end
12
+
13
+ it 'assigns the context' do
14
+ expect(subject.context).to eq(context)
15
+ end
16
+ end
17
+
18
+ describe '#read' do
19
+
20
+ it 'is not implemented' do
21
+ expect{ subject.read }.to raise_error NotImplementedError
22
+ end
23
+ end
24
+
25
+ describe '#write' do
26
+
27
+ it 'is not implemented' do
28
+ expect{ subject.write feature_name }.to raise_error NotImplementedError
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,10 @@
1
+ Feature: Feature flipping at an application level
2
+
3
+ Scenario Outline: Features can be declared as enabled or disabled and remain as such
4
+ When I define a feature that is '<enabled_or_disabled>'
5
+ Then the feature is '<enabled_or_disabled>'
6
+
7
+ Examples:
8
+ | enabled_or_disabled |
9
+ | enabled |
10
+ | disabled |
@@ -0,0 +1,47 @@
1
+ describe FlipFab do
2
+ let(:name) { :example_feature }
3
+
4
+ it 'runs the feature' do
5
+ feature
6
+ end
7
+
8
+ step 'I define a feature that is :enabled_or_disabled' do |enabled_or_disabled|
9
+ described_class.define_feature name, { default: enabled_or_disabled.to_sym }
10
+ end
11
+
12
+ step 'the feature is :enabled_or_disabled' do |enabled_or_disabled|
13
+ expect(described_class.features[name].enabled?).to eq(enabled_or_disabled == 'enabled')
14
+ end
15
+
16
+ it 'initializes features' do
17
+ expect(described_class.features).to be_a FlipFab::FeaturesByName
18
+ end
19
+
20
+ context '.define_feature' do
21
+ subject{ described_class.define_feature name }
22
+ after{ described_class.features.clear }
23
+
24
+ it 'returns the feature' do
25
+ expect(subject).to be_a FlipFab::Feature
26
+ expect(subject.name).to eq(:example_feature)
27
+ end
28
+
29
+ context 'when the feature exists' do
30
+
31
+ it 'overwrites the existing feature' do
32
+ existing_feature = described_class.define_feature name
33
+ expect{ subject }.not_to change{ described_class.features.count }.from(1)
34
+ expect(subject).not_to eq(existing_feature)
35
+ end
36
+ end
37
+
38
+ context 'when the feature does not exist' do
39
+
40
+ it 'saves the feature' do
41
+ expect{ subject }.to change{ described_class.features.count }.from(0).to(1)
42
+ expected_feature = subject
43
+ expect(described_class.features[:example_feature]).to eq(expected_feature)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,93 @@
1
+ require 'flip_fab'
2
+
3
+ Dir['./spec/support/**/*.rb'].sort.each { |f| require f}
4
+
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
8
+ # file to always be loaded, without a need to explicitly require it in any files.
9
+ #
10
+ # Given that it is always loaded, you are encouraged to keep this file as
11
+ # light-weight as possible. Requiring heavyweight dependencies from this file
12
+ # will add to the boot time of your test suite on EVERY test run, even for an
13
+ # individual file that may not need all of that loaded. Instead, consider making
14
+ # a separate helper file that requires the additional dependencies and performs
15
+ # the additional setup, and require it from the spec files that actually need it.
16
+ #
17
+ # The `.rspec` file also contains a few flags that are not defaults but that
18
+ # users commonly want.
19
+ #
20
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # The settings below are suggested to provide a good initial experience
46
+ # with RSpec, but feel free to customize to your heart's content.
47
+ =begin
48
+ # These two settings work together to allow you to limit a spec run
49
+ # to individual examples or groups you care about by tagging them with
50
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
51
+ # get run.
52
+ config.filter_run :focus
53
+ config.run_all_when_everything_filtered = true
54
+
55
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
56
+ # For more details, see:
57
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
58
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
59
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
60
+ config.disable_monkey_patching!
61
+
62
+ # This setting enables warnings. It's recommended, but in some cases may
63
+ # be too noisy due to issues in dependencies.
64
+ config.warnings = true
65
+
66
+ # Many RSpec users commonly either run the entire suite or an individual
67
+ # file, and it's useful to allow more verbose output when running an
68
+ # individual spec file.
69
+ if config.files_to_run.one?
70
+ # Use the documentation formatter for detailed output,
71
+ # unless a formatter has already been configured
72
+ # (e.g. via a command-line flag).
73
+ config.default_formatter = 'doc'
74
+ end
75
+
76
+ # Print the 10 slowest examples and example groups at the
77
+ # end of the spec run, to help surface which specs are running
78
+ # particularly slow.
79
+ config.profile_examples = 10
80
+
81
+ # Run specs in random order to surface order dependencies. If you find an
82
+ # order dependency and want to debug it, you can fix the order by providing
83
+ # the seed, which is printed after each run.
84
+ # --seed 1234
85
+ config.order = :random
86
+
87
+ # Seed global randomization in this process using the `--seed` CLI option.
88
+ # Setting this allows you to use `--seed` to deterministically reproduce
89
+ # test failures related to randomization by passing the same `--seed` value
90
+ # as the one that triggered the failure.
91
+ Kernel.srand config.seed
92
+ =end
93
+ end
@@ -0,0 +1,16 @@
1
+ class TestApp
2
+ include FlipFab::Helper
3
+
4
+ attr_reader :request, :response, :params, :contextual_features
5
+
6
+ def call env
7
+ @request = Rack::Request.new env
8
+ @response = Rack::Response.new
9
+ @params = request.params
10
+
11
+ @contextual_features = features
12
+
13
+ request.cookies.each{|k,v| response.set_cookie k, v }
14
+ [response.status, response.header, response.body]
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ class TestContext
2
+ include FlipFab::Helper
3
+
4
+ attr_reader :feature_states, :params
5
+
6
+ def initialize feature_states={}, params={}
7
+ @feature_states = feature_states
8
+ @params = params
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ class TestMultiplePersistence < FlipFab::Persistence
2
+
3
+ def initialize feature_name, context
4
+ super
5
+ end
6
+
7
+ def read
8
+ context.feature_states[:different_example_feature]
9
+ end
10
+
11
+ def write value
12
+ context.feature_states[:different_example_feature] = value
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class TestPersistence < FlipFab::Persistence
2
+
3
+ def initialize feature_name, context
4
+ super
5
+ end
6
+
7
+ def read
8
+ context.feature_states[feature_name]
9
+ end
10
+
11
+ def write state
12
+ context.feature_states[feature_name] = state
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ class TestRackContext
2
+ include FlipFab::Helper
3
+
4
+ attr_reader :request, :response
5
+
6
+ def initialize cookies, host
7
+ @request = Rack::Request.new({ 'HTTP_COOKIE' => cookies, 'HTTP_HOST' => host })
8
+ @response = Rack::Response.new
9
+ request.cookies.each{|k,v| response.set_cookie k, v }
10
+ end
11
+
12
+ def response_cookies
13
+ response.header['Set-Cookie']
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flip_fab
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Simply Business
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A gem providing persistent, per-user feature flipping to Rack applications.
14
+ email:
15
+ - tech@simplybusiness.co.uk
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rspec"
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - LICENSE.txt
24
+ - README.md
25
+ - example/rails_app/.gitignore
26
+ - example/rails_app/Gemfile
27
+ - example/rails_app/Gemfile.lock
28
+ - example/rails_app/README.rdoc
29
+ - example/rails_app/Rakefile
30
+ - example/rails_app/app/assets/images/.keep
31
+ - example/rails_app/app/assets/images/justin_beaver.jpg
32
+ - example/rails_app/app/assets/images/regular_beaver.jpg
33
+ - example/rails_app/app/assets/javascripts/application.js
34
+ - example/rails_app/app/assets/javascripts/beavers.js.coffee
35
+ - example/rails_app/app/assets/stylesheets/application.css
36
+ - example/rails_app/app/assets/stylesheets/beavers.css.scss
37
+ - example/rails_app/app/assets/stylesheets/scaffolds.css.scss
38
+ - example/rails_app/app/controllers/application_controller.rb
39
+ - example/rails_app/app/controllers/beavers_controller.rb
40
+ - example/rails_app/app/controllers/concerns/.keep
41
+ - example/rails_app/app/helpers/application_helper.rb
42
+ - example/rails_app/app/helpers/beavers_helper.rb
43
+ - example/rails_app/app/mailers/.keep
44
+ - example/rails_app/app/models/.keep
45
+ - example/rails_app/app/models/beaver.rb
46
+ - example/rails_app/app/models/concerns/.keep
47
+ - example/rails_app/app/views/beavers/_form.html.erb
48
+ - example/rails_app/app/views/beavers/edit.html.erb
49
+ - example/rails_app/app/views/beavers/index.html.erb
50
+ - example/rails_app/app/views/beavers/index.json.jbuilder
51
+ - example/rails_app/app/views/beavers/new.html.erb
52
+ - example/rails_app/app/views/beavers/show.html.erb
53
+ - example/rails_app/app/views/beavers/show.json.jbuilder
54
+ - example/rails_app/app/views/layouts/application.html.erb
55
+ - example/rails_app/bin/bundle
56
+ - example/rails_app/bin/rails
57
+ - example/rails_app/bin/rake
58
+ - example/rails_app/config.ru
59
+ - example/rails_app/config/application.rb
60
+ - example/rails_app/config/boot.rb
61
+ - example/rails_app/config/database.yml
62
+ - example/rails_app/config/environment.rb
63
+ - example/rails_app/config/environments/development.rb
64
+ - example/rails_app/config/environments/test.rb
65
+ - example/rails_app/config/initializers/backtrace_silencers.rb
66
+ - example/rails_app/config/initializers/cookies_serializer.rb
67
+ - example/rails_app/config/initializers/filter_parameter_logging.rb
68
+ - example/rails_app/config/initializers/flip_fab.rb
69
+ - example/rails_app/config/initializers/inflections.rb
70
+ - example/rails_app/config/initializers/mime_types.rb
71
+ - example/rails_app/config/initializers/session_store.rb
72
+ - example/rails_app/config/initializers/wrap_parameters.rb
73
+ - example/rails_app/config/locales/en.yml
74
+ - example/rails_app/config/rabbit_feed.yml
75
+ - example/rails_app/config/routes.rb
76
+ - example/rails_app/config/secrets.yml
77
+ - example/rails_app/config/unicorn.rb
78
+ - example/rails_app/db/migrate/20140424102400_create_beavers.rb
79
+ - example/rails_app/db/schema.rb
80
+ - example/rails_app/db/seeds.rb
81
+ - example/rails_app/lib/assets/.keep
82
+ - example/rails_app/lib/tasks/.keep
83
+ - example/rails_app/log/.keep
84
+ - example/rails_app/public/404.html
85
+ - example/rails_app/public/422.html
86
+ - example/rails_app/public/500.html
87
+ - example/rails_app/public/favicon.ico
88
+ - example/rails_app/public/robots.txt
89
+ - example/rails_app/spec/rails_helper.rb
90
+ - example/rails_app/spec/spec_helper.rb
91
+ - example/rails_app/test/controllers/.keep
92
+ - example/rails_app/test/controllers/beavers_controller_test.rb
93
+ - example/rails_app/test/fixtures/.keep
94
+ - example/rails_app/test/fixtures/beavers.yml
95
+ - example/rails_app/test/helpers/.keep
96
+ - example/rails_app/test/helpers/beavers_helper_test.rb
97
+ - example/rails_app/test/integration/.keep
98
+ - example/rails_app/test/mailers/.keep
99
+ - example/rails_app/test/models/.keep
100
+ - example/rails_app/test/models/beaver_test.rb
101
+ - example/rails_app/test/test_helper.rb
102
+ - flip_fab.gemspec
103
+ - lib/flip_fab.rb
104
+ - lib/flip_fab/contextual_feature.rb
105
+ - lib/flip_fab/cookie_persistence.rb
106
+ - lib/flip_fab/feature.rb
107
+ - lib/flip_fab/features_by_name.rb
108
+ - lib/flip_fab/helper.rb
109
+ - lib/flip_fab/persistence.rb
110
+ - lib/flip_fab/version.rb
111
+ - spec/lib/flip_fab.feature
112
+ - spec/lib/flip_fab/contextual_feature_spec.rb
113
+ - spec/lib/flip_fab/cookie_persistence.feature
114
+ - spec/lib/flip_fab/cookie_persistence_spec.rb
115
+ - spec/lib/flip_fab/feature_spec.rb
116
+ - spec/lib/flip_fab/features_by_name_spec.rb
117
+ - spec/lib/flip_fab/helper.feature
118
+ - spec/lib/flip_fab/helper_spec.rb
119
+ - spec/lib/flip_fab/persistence_spec.rb
120
+ - spec/lib/flip_fab_spec.rb
121
+ - spec/spec_helper.rb
122
+ - spec/support/test_app.rb
123
+ - spec/support/test_context.rb
124
+ - spec/support/test_multiple_persistence.rb
125
+ - spec/support/test_persistence.rb
126
+ - spec/support/test_rack_context.rb
127
+ homepage: https://github.com/simplybusiness/flip_fab
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.0.14
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: A gem providing persistent, per-user feature flipping to Rack applications.
151
+ test_files:
152
+ - spec/lib/flip_fab.feature
153
+ - spec/lib/flip_fab/contextual_feature_spec.rb
154
+ - spec/lib/flip_fab/cookie_persistence.feature
155
+ - spec/lib/flip_fab/cookie_persistence_spec.rb
156
+ - spec/lib/flip_fab/feature_spec.rb
157
+ - spec/lib/flip_fab/features_by_name_spec.rb
158
+ - spec/lib/flip_fab/helper.feature
159
+ - spec/lib/flip_fab/helper_spec.rb
160
+ - spec/lib/flip_fab/persistence_spec.rb
161
+ - spec/lib/flip_fab_spec.rb
162
+ - spec/spec_helper.rb
163
+ - spec/support/test_app.rb
164
+ - spec/support/test_context.rb
165
+ - spec/support/test_multiple_persistence.rb
166
+ - spec/support/test_persistence.rb
167
+ - spec/support/test_rack_context.rb
168
+ has_rdoc: