green_flag 0.2.0 → 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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.hound.yml +4 -0
  4. data/.rubocop.yml +1260 -0
  5. data/CONTRIBUTING.md +28 -0
  6. data/app/assets/javascripts/green_flag/admin/feature-deletion.js +3 -0
  7. data/app/assets/javascripts/green_flag/admin/features.js +1 -1
  8. data/app/assets/stylesheets/green_flag/admin/features.css.scss +5 -1
  9. data/app/controllers/green_flag/admin/features_controller.rb +22 -2
  10. data/app/helpers/green_flag/application_helper.rb +1 -0
  11. data/app/models/green_flag/feature.rb +13 -1
  12. data/app/views/green_flag/admin/features/_delete_flag_button.html.erb +18 -0
  13. data/app/views/green_flag/admin/features/index.html.erb +5 -0
  14. data/app/views/green_flag/admin/features/show.html.erb +4 -2
  15. data/green_flag.gemspec +1 -1
  16. data/lib/green_flag/version.rb +1 -1
  17. data/spec/controllers/admin/features_controller_spec.rb +51 -2
  18. data/spec/dummy/log/development.log +54000 -7025
  19. data/spec/dummy/log/test.log +37566 -31044
  20. data/spec/dummy/tmp/cache/assets/{D68/760/sprockets%2Fea24808c41a3dff75b995b0f090e1a6a → C4A/640/sprockets%2F8a0527fb4c2402950e34518216e856b5} +0 -0
  21. data/spec/dummy/tmp/cache/assets/C6A/420/sprockets%2F10f5bf24a82184a4790391b0321bd318 +0 -0
  22. data/spec/dummy/tmp/cache/assets/CB2/480/sprockets%2Fdffc90cb8265f2042063557905188b1f +0 -0
  23. data/spec/dummy/tmp/cache/assets/CB9/C30/sprockets%2F8c5e58364159f49f2242f171653cadf1 +0 -0
  24. data/spec/dummy/tmp/cache/assets/CEA/0F0/sprockets%2F7d5273f602c66c790a79a75c088ff01d +0 -0
  25. data/spec/dummy/tmp/cache/assets/{C89/D60/sprockets%2F73cd073739a0655341b7278fae57518f → D05/9B0/sprockets%2Fa5b09f162635302e890302aed86bbd6e} +0 -0
  26. data/spec/dummy/tmp/cache/assets/D1A/760/sprockets%2Fc2f1fda4977960d755da14289d49b51b +0 -0
  27. data/spec/dummy/tmp/cache/assets/D34/660/sprockets%2Fcfd906f8a0a2386735d1dcf52cc40403 +0 -0
  28. data/spec/dummy/tmp/cache/assets/{E34/D30/sprockets%2F99c2d0bbd78f1b867beeb3a2eefda618 → D3E/110/sprockets%2Fcb870c7f25e6162da93a720e1be65c76} +0 -0
  29. data/spec/dummy/tmp/cache/assets/D3E/340/sprockets%2Fad85a878e73a3075722c09b0bdc17cd8 +0 -0
  30. data/spec/dummy/tmp/cache/assets/{E07/200/sprockets%2F82a8ce7f5bcfb07f773df4cbfeb04762 → D3E/E90/sprockets%2F07bfdbaf75a7c43c05315078db879c43} +0 -0
  31. data/spec/dummy/tmp/cache/assets/{CE7/FF0/sprockets%2Fe45f3a7675a8c5a5b064117792bf5e28 → D40/260/sprockets%2F35049c3c82baf75b9adfc9662c05e172} +0 -0
  32. data/spec/dummy/tmp/cache/assets/D62/040/sprockets%2F388ca040babbebd910f7338b606736bd +0 -0
  33. data/spec/dummy/tmp/cache/assets/D6F/650/sprockets%2F9710be3c17f826e702a9ccea335cdf83 +0 -0
  34. data/spec/dummy/tmp/cache/assets/{D07/670/sprockets%2F761d03a66b753d628feccd12072c814c → D82/990/sprockets%2F708fb789dee8ecdf5a4a39b9216c1295} +0 -0
  35. data/spec/dummy/tmp/cache/assets/D8D/1D0/sprockets%2F0e45f412d3a303eda9d7d10d8fc3a5d3 +0 -0
  36. data/spec/dummy/tmp/cache/assets/D9D/660/sprockets%2Fd306fa5f1db77c33117fbf27276b3ffd +0 -0
  37. data/spec/dummy/tmp/cache/assets/{DB2/0C0/sprockets%2F95cf35cd3e97774df3c41ee0ef564a8d → DF4/060/sprockets%2F3a6c5e41f435db6af7fb91fa0da49bb1} +0 -0
  38. data/spec/dummy/tmp/cache/assets/{D13/270/sprockets%2F701a30cd450ae3cfa114092bafc16004 → DF8/280/sprockets%2Fa245a66abbfe76d9de5aa5a40c557f0e} +0 -0
  39. data/spec/dummy/tmp/cache/assets/DFC/AB0/sprockets%2Fcbca52f6723bcc63ade1b269e299a7bf +0 -0
  40. data/spec/dummy/tmp/cache/assets/{D6A/580/sprockets%2F18c12847aa1bb46ce9b5661f0e9e5fb0 → E0D/870/sprockets%2Fc21ca057d9f87e8cb797dbe5b8fe3bd2} +0 -0
  41. data/spec/dummy/tmp/pids/server.pid +1 -0
  42. data/spec/factories/green_flag/feature_decision.rb +5 -0
  43. data/spec/factories/green_flag/feature_event.rb +6 -0
  44. data/spec/factories/green_flag/rule.rb +2 -2
  45. data/spec/models/green_flag/feature_spec.rb +166 -108
  46. metadata +60 -60
  47. data/Gemfile.lock +0 -143
  48. data/spec/dummy/tmp/cache/assets/C47/3D0/sprockets%2F8f17c33229239b023190617bf2e915a3 +0 -0
  49. data/spec/dummy/tmp/cache/assets/C81/770/sprockets%2Fdbcf34796b062155788f0b550808541a +0 -0
  50. data/spec/dummy/tmp/cache/assets/CB6/8F0/sprockets%2F5ea0f1f2583683678e122a9a9391a80f +0 -0
  51. data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  52. data/spec/dummy/tmp/cache/assets/D10/860/sprockets%2F4582878dbb5b72bfa76615d31b34ed51 +0 -0
  53. data/spec/dummy/tmp/cache/assets/D15/C10/sprockets%2F6f42f843c916d7864a0dfa912fb3194a +0 -0
  54. data/spec/dummy/tmp/cache/assets/D18/860/sprockets%2Fce00769800ae939cebb28501947ea96f +0 -0
  55. data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  56. data/spec/dummy/tmp/cache/assets/D4A/970/sprockets%2F2a7d3b403cbdd8b59d57d26964ea5768 +0 -0
  57. data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  58. data/spec/dummy/tmp/cache/assets/D59/090/sprockets%2F88788ba6a64e6279624e5c2ff7eead53 +0 -0
  59. data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  60. data/spec/dummy/tmp/cache/assets/D5C/330/sprockets%2Fd1b1c9a53f4a8a5827e5b02bf0e100e8 +0 -0
  61. data/spec/dummy/tmp/cache/assets/DA1/210/sprockets%2F25a2979e392c8bc3adce7075cf19ab4b +0 -0
  62. data/spec/dummy/tmp/cache/assets/DA9/2C0/sprockets%2Ff95d82b2bbb6db8ffe1a87f67b415291 +0 -0
  63. data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  64. data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,28 @@
1
+ # Contributing to GreenFlag
2
+
3
+ ## Developing
4
+
5
+ We're following a pretty standard process for a Github hosted project:
6
+
7
+ - Fork the project (core team members can skip this and work directly in this repo)
8
+ - Clone to your local machine
9
+ - Create a branch for your changes
10
+ - Push your branch to Github
11
+ - Submit a PR to master.
12
+ - After code review, your PR will be merged into master for inclusion in the next release.
13
+
14
+ ## Release
15
+
16
+ The `gem-release` gem is included as a development dependency. Documented here is the "normal release" process using that gem. More options can be found here: https://github.com/svenfuchs/gem-release
17
+
18
+ - You should be on the `master` branch, with all of the releasable code merged in.
19
+ - Run `rake spec` to make sure the specs pass.
20
+ - Run this command: `gem bump --version minor --tag`
21
+ - That's for a "minor" version. You can also use "major" or "patch".
22
+ - This does the following:
23
+ - Increments the version in `lib/green_flag/version.rb` and commits that change
24
+ - Creates a tag for the new version
25
+ - Pushes the commits and tag to Github
26
+ - Run this command: `gem release`
27
+ - This actually pushes the gem to RubyGems.
28
+ - In your project that uses GreenFlag, update to the latest: `bundle update green_flag`
@@ -0,0 +1,3 @@
1
+ $(function() {
2
+ $('.tooltip-wrapper').tooltip({position: 'bottom'});
3
+ });
@@ -350,4 +350,4 @@ GreenFlag.DecisionsView = Backbone.Marionette.ItemView.extend({
350
350
  this.model.save({ forget_disabled: true });
351
351
  },
352
352
 
353
- });
353
+ });
@@ -37,4 +37,8 @@ ul.decisions-made-summary {
37
37
  font-weight: 500;
38
38
  font-size: 24px;
39
39
  }
40
- }
40
+ }
41
+
42
+ .tooltip-wrapper {
43
+ display: inline-block;
44
+ }
@@ -1,16 +1,29 @@
1
1
  class GreenFlag::Admin::FeaturesController < ApplicationController
2
-
3
2
  layout 'green_flag/application'
3
+ helper_method :flash_class
4
4
 
5
5
  def index
6
6
  @features = GreenFlag::Feature.order(:created_at).all
7
7
  end
8
8
 
9
9
  def show
10
- @feature = GreenFlag::Feature.find(params[:id])
10
+ @feature = GreenFlag::Feature.where(id: params[:id]).first
11
+
11
12
  @visitor_groups = GreenFlag::VisitorGroup.all.map { |group| { key: group.key, description: group.description } }
12
13
  end
13
14
 
15
+ def destroy
16
+ @feature = GreenFlag::Feature.where(id: params[:id]).first
17
+
18
+ if @feature.present?
19
+ destroy_feature
20
+ else
21
+ flash[:error] = "The feature could not be found."
22
+ end
23
+
24
+ redirect_to action: :index
25
+ end
26
+
14
27
  def current_visitor_status
15
28
  @feature = GreenFlag::Feature.find(params[:id])
16
29
  fd = GreenFlag::FeatureDecision.for_feature(@feature.id).where(site_visitor_id: current_site_visitor.id).first
@@ -19,6 +32,13 @@ class GreenFlag::Admin::FeaturesController < ApplicationController
19
32
 
20
33
  private
21
34
 
35
+ def destroy_feature
36
+ flash[:notice] = "Feature \"#{@feature.code}\" has been successfully deleted."
37
+
38
+ @feature.delete_associated_data
39
+ @feature.destroy
40
+ end
41
+
22
42
  def status_text(feature_decison)
23
43
  if feature_decison.nil? || feature_decison.undecided?
24
44
  "Undecided"
@@ -2,3 +2,4 @@ module GreenFlag
2
2
  module ApplicationHelper
3
3
  end
4
4
  end
5
+
@@ -61,7 +61,19 @@ class GreenFlag::Feature < ActiveRecord::Base
61
61
  def fully_disabled?
62
62
  rules.count == 0 || rules.all? { |rule| rule.percentage == 0 }
63
63
  end
64
-
64
+
65
+ def destroyable?
66
+ fully_enabled? || fully_disabled?
67
+ end
68
+
69
+ def delete_associated_data
70
+ GreenFlag::Feature.transaction do
71
+ GreenFlag::Rule.where(feature_id: id).delete_all
72
+ GreenFlag::FeatureDecision.where(feature_id: id).delete_all
73
+ GreenFlag::FeatureEvent.where(feature_id: id).delete_all
74
+ end
75
+ end
76
+
65
77
  private
66
78
 
67
79
  def decide_feature_decision(feature_decision)
@@ -0,0 +1,18 @@
1
+ <%
2
+ button_class = @feature.destroyable? ? 'btn btn-danger' : 'btn btn-danger disabled'
3
+
4
+ confirmation_message = "Are you sure? The feature and all associated rules and \
5
+ decisions will be permanently deleted."
6
+ %>
7
+
8
+ <% unless @feature.destroyable? %>
9
+ <div class="tooltip-wrapper" data-title="For deletion, the rules must be set to
10
+ 100% or 0% for all groups. After setting the rule percentages, refresh this page.">
11
+ <% end %>
12
+
13
+ <%= link_to "Delete Flag", admin_feature_path(@feature.id), class: button_class,
14
+ data: { confirm: confirmation_message }, method: :delete %>
15
+
16
+ <% unless @feature.destroyable? %>
17
+ </div>
18
+ <% end %>
@@ -1,3 +1,8 @@
1
+ <% flash.each do |key, value| %>
2
+ <div class="alert alert-info">
3
+ <%= value %>
4
+ </div>
5
+ <% end %>
1
6
 
2
7
  <div class="header clearfix">
3
8
  <h1><%= link_to 'Green Flag', admin_features_path %></h1>
@@ -103,8 +103,6 @@
103
103
  </ul>
104
104
 
105
105
  </div>
106
-
107
-
108
106
  </script>
109
107
 
110
108
  <%# Templates - white list %>
@@ -134,8 +132,12 @@
134
132
  <h2>Your Status <span class="label {{labelClass}}">{{status}}</span></h2>
135
133
  </script>
136
134
 
135
+ <%= render 'delete_flag_button' %>
136
+
137
137
  <%# Javascript kickstart %>
138
138
  <%= javascript_include_tag 'green_flag/admin/features' %>
139
+ <%= javascript_include_tag 'green_flag/admin/feature-deletion' %>
140
+
139
141
  <script>
140
142
  GreenFlag.FeatureEditor.start({
141
143
  feature: <%= @feature.to_json.html_safe %>,
data/green_flag.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency "activerecord-concurrent-index"
29
29
  s.add_dependency "sass-rails"
30
30
 
31
- s.add_development_dependency 'rspec-rails'
31
+ s.add_development_dependency 'rspec-rails', "~> 2"
32
32
  s.add_development_dependency 'factory_girl_rails'
33
33
  s.add_development_dependency 'capybara'
34
34
  s.add_development_dependency 'gem-release'
@@ -1,3 +1,3 @@
1
1
  module GreenFlag
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe GreenFlag::Admin::FeaturesController do
4
-
5
4
  let(:feature) { GreenFlag::Feature.create(code: 'foo') }
6
5
 
7
6
  describe '#index' do
@@ -16,6 +15,56 @@ describe GreenFlag::Admin::FeaturesController do
16
15
  get :show, :id => feature.id
17
16
  expect(response).to be_success
18
17
  end
19
- end
18
+ end
19
+
20
+ describe "#destroy" do
21
+ subject { delete :destroy, id: feature.id }
22
+
23
+ it "redirects to the index action" do
24
+ expect(subject).to redirect_to action: :index
25
+ end
26
+
27
+ context "when the feature can be deleted" do
28
+ before(:each) do
29
+ 5.times do
30
+ FactoryGirl.create(:green_flag_rule, feature_id: feature.id)
31
+ FactoryGirl.create(:green_flag_feature_event, feature_id: feature.id)
32
+ FactoryGirl.create(:green_flag_feature_decision, feature_id: feature.id)
33
+ end
34
+
35
+ subject
36
+ end
37
+
38
+ it "deletes the feature" do
39
+ expect(GreenFlag::Feature.find_by_id(feature.id)).to be_nil
40
+ end
20
41
 
42
+ it "deletes the feature's rules" do
43
+ expect(GreenFlag::Rule.where(feature_id: feature.id)).to eq []
44
+ end
45
+
46
+ it "deletes the feature's events" do
47
+ expect(GreenFlag::FeatureEvent.where(feature_id: feature.id)).to eq []
48
+ end
49
+
50
+ it "deletes the feature's feature decisions" do
51
+ expect(GreenFlag::FeatureDecision.where(feature_id: feature.id)).to eq []
52
+ end
53
+
54
+ it "sets a successful flash notice" do
55
+ expect(flash[:notice]).to eq "Feature \"#{feature.code}\" has been \
56
+ successfully deleted."
57
+ end
58
+ end
59
+
60
+ context "when the feature cannot be found" do
61
+ it "sets a flash error indicating the error" do
62
+ feature.destroy
63
+
64
+ subject
65
+
66
+ expect(flash[:error]).to eq "The feature could not be found."
67
+ end
68
+ end
69
+ end
21
70
  end