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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.hound.yml +4 -0
- data/.rubocop.yml +1260 -0
- data/CONTRIBUTING.md +28 -0
- data/app/assets/javascripts/green_flag/admin/feature-deletion.js +3 -0
- data/app/assets/javascripts/green_flag/admin/features.js +1 -1
- data/app/assets/stylesheets/green_flag/admin/features.css.scss +5 -1
- data/app/controllers/green_flag/admin/features_controller.rb +22 -2
- data/app/helpers/green_flag/application_helper.rb +1 -0
- data/app/models/green_flag/feature.rb +13 -1
- data/app/views/green_flag/admin/features/_delete_flag_button.html.erb +18 -0
- data/app/views/green_flag/admin/features/index.html.erb +5 -0
- data/app/views/green_flag/admin/features/show.html.erb +4 -2
- data/green_flag.gemspec +1 -1
- data/lib/green_flag/version.rb +1 -1
- data/spec/controllers/admin/features_controller_spec.rb +51 -2
- data/spec/dummy/log/development.log +54000 -7025
- data/spec/dummy/log/test.log +37566 -31044
- data/spec/dummy/tmp/cache/assets/{D68/760/sprockets%2Fea24808c41a3dff75b995b0f090e1a6a → C4A/640/sprockets%2F8a0527fb4c2402950e34518216e856b5} +0 -0
- data/spec/dummy/tmp/cache/assets/C6A/420/sprockets%2F10f5bf24a82184a4790391b0321bd318 +0 -0
- data/spec/dummy/tmp/cache/assets/CB2/480/sprockets%2Fdffc90cb8265f2042063557905188b1f +0 -0
- data/spec/dummy/tmp/cache/assets/CB9/C30/sprockets%2F8c5e58364159f49f2242f171653cadf1 +0 -0
- data/spec/dummy/tmp/cache/assets/CEA/0F0/sprockets%2F7d5273f602c66c790a79a75c088ff01d +0 -0
- data/spec/dummy/tmp/cache/assets/{C89/D60/sprockets%2F73cd073739a0655341b7278fae57518f → D05/9B0/sprockets%2Fa5b09f162635302e890302aed86bbd6e} +0 -0
- data/spec/dummy/tmp/cache/assets/D1A/760/sprockets%2Fc2f1fda4977960d755da14289d49b51b +0 -0
- data/spec/dummy/tmp/cache/assets/D34/660/sprockets%2Fcfd906f8a0a2386735d1dcf52cc40403 +0 -0
- data/spec/dummy/tmp/cache/assets/{E34/D30/sprockets%2F99c2d0bbd78f1b867beeb3a2eefda618 → D3E/110/sprockets%2Fcb870c7f25e6162da93a720e1be65c76} +0 -0
- data/spec/dummy/tmp/cache/assets/D3E/340/sprockets%2Fad85a878e73a3075722c09b0bdc17cd8 +0 -0
- data/spec/dummy/tmp/cache/assets/{E07/200/sprockets%2F82a8ce7f5bcfb07f773df4cbfeb04762 → D3E/E90/sprockets%2F07bfdbaf75a7c43c05315078db879c43} +0 -0
- data/spec/dummy/tmp/cache/assets/{CE7/FF0/sprockets%2Fe45f3a7675a8c5a5b064117792bf5e28 → D40/260/sprockets%2F35049c3c82baf75b9adfc9662c05e172} +0 -0
- data/spec/dummy/tmp/cache/assets/D62/040/sprockets%2F388ca040babbebd910f7338b606736bd +0 -0
- data/spec/dummy/tmp/cache/assets/D6F/650/sprockets%2F9710be3c17f826e702a9ccea335cdf83 +0 -0
- data/spec/dummy/tmp/cache/assets/{D07/670/sprockets%2F761d03a66b753d628feccd12072c814c → D82/990/sprockets%2F708fb789dee8ecdf5a4a39b9216c1295} +0 -0
- data/spec/dummy/tmp/cache/assets/D8D/1D0/sprockets%2F0e45f412d3a303eda9d7d10d8fc3a5d3 +0 -0
- data/spec/dummy/tmp/cache/assets/D9D/660/sprockets%2Fd306fa5f1db77c33117fbf27276b3ffd +0 -0
- data/spec/dummy/tmp/cache/assets/{DB2/0C0/sprockets%2F95cf35cd3e97774df3c41ee0ef564a8d → DF4/060/sprockets%2F3a6c5e41f435db6af7fb91fa0da49bb1} +0 -0
- data/spec/dummy/tmp/cache/assets/{D13/270/sprockets%2F701a30cd450ae3cfa114092bafc16004 → DF8/280/sprockets%2Fa245a66abbfe76d9de5aa5a40c557f0e} +0 -0
- data/spec/dummy/tmp/cache/assets/DFC/AB0/sprockets%2Fcbca52f6723bcc63ade1b269e299a7bf +0 -0
- data/spec/dummy/tmp/cache/assets/{D6A/580/sprockets%2F18c12847aa1bb46ce9b5661f0e9e5fb0 → E0D/870/sprockets%2Fc21ca057d9f87e8cb797dbe5b8fe3bd2} +0 -0
- data/spec/dummy/tmp/pids/server.pid +1 -0
- data/spec/factories/green_flag/feature_decision.rb +5 -0
- data/spec/factories/green_flag/feature_event.rb +6 -0
- data/spec/factories/green_flag/rule.rb +2 -2
- data/spec/models/green_flag/feature_spec.rb +166 -108
- metadata +60 -60
- data/Gemfile.lock +0 -143
- data/spec/dummy/tmp/cache/assets/C47/3D0/sprockets%2F8f17c33229239b023190617bf2e915a3 +0 -0
- data/spec/dummy/tmp/cache/assets/C81/770/sprockets%2Fdbcf34796b062155788f0b550808541a +0 -0
- data/spec/dummy/tmp/cache/assets/CB6/8F0/sprockets%2F5ea0f1f2583683678e122a9a9391a80f +0 -0
- data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/D10/860/sprockets%2F4582878dbb5b72bfa76615d31b34ed51 +0 -0
- data/spec/dummy/tmp/cache/assets/D15/C10/sprockets%2F6f42f843c916d7864a0dfa912fb3194a +0 -0
- data/spec/dummy/tmp/cache/assets/D18/860/sprockets%2Fce00769800ae939cebb28501947ea96f +0 -0
- data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/D4A/970/sprockets%2F2a7d3b403cbdd8b59d57d26964ea5768 +0 -0
- data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/tmp/cache/assets/D59/090/sprockets%2F88788ba6a64e6279624e5c2ff7eead53 +0 -0
- data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/D5C/330/sprockets%2Fd1b1c9a53f4a8a5827e5b02bf0e100e8 +0 -0
- data/spec/dummy/tmp/cache/assets/DA1/210/sprockets%2F25a2979e392c8bc3adce7075cf19ab4b +0 -0
- data/spec/dummy/tmp/cache/assets/DA9/2C0/sprockets%2Ff95d82b2bbb6db8ffe1a87f67b415291 +0 -0
- data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
- 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`
|
|
@@ -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.
|
|
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"
|
|
@@ -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 %>
|
|
@@ -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'
|
data/lib/green_flag/version.rb
CHANGED
|
@@ -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
|