ffe 0.2.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd421a2265cc4254c4f11d652831e595994412dc411adbb8d6082b0cebd354de
4
- data.tar.gz: a93f928f0810704b1fb5837719753a58d23567220065fb15e41ef705e24b1bc1
3
+ metadata.gz: 8714db1c7883a34c1d3d855f04531060fe1dfe11b568bee0508570f4e4c1942a
4
+ data.tar.gz: e781c9895aeeb7ccc047b684805216d81ee4e3adc1eece5e7ee3fe9078f4a715
5
5
  SHA512:
6
- metadata.gz: 19f5e63d4a2c7616cd418b143c161850fa3329e0dce8fcb3118ed11f7cccd272ffa955d14fa0ce1e1b08d7e3a92ca3c87d46929eedfe9b037ac8e4dbe3c3bf22
7
- data.tar.gz: 18f38bf47143ca87795e04163afd2d6f02b05c5ebed3d25949b89dc3195777fb7822847cf60855cfd5f8f6a86c3685adf6356f9f437034a4c2afe8236c0a7a47
6
+ metadata.gz: 5ca29b54bfe343aa8dd8fee221a0921bf8ce349b177e759d65efecdabe69d8c824a439d507b687d7bfd42bf72ab0492ed38365cad0febc90ef0c4f7239908002
7
+ data.tar.gz: 792f322fe595ec922daf165dee955ee7550a02ab6ef0354ef007fdb60ac44248f48b1c878ee0d324161a43b1b5d43c3a6e7dd42eabbefd45322be00734158f9b
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  A minimalistic Feature Flag engine, cause i was bored of unleash and other overloaded ones.
4
4
 
5
5
  ## Installation
6
+
6
7
  Add this line to your application's Gemfile:
7
8
 
8
9
  ```ruby
@@ -28,6 +29,9 @@ config.env_variable = 'RAILS_ENV'
28
29
  config.queue_adapter = :solid_queue
29
30
  ```
30
31
 
32
+ It also adds a loader for `feature_flags.json`, so you can easily load feature flags from a file.
33
+ But to this later under `Scenarios`.
34
+
31
35
  Install the migration with:
32
36
  ```bash
33
37
  $ bin/rails ffe:install:migrations
@@ -52,17 +56,50 @@ Run your app and go to [http://localhost:3000/ffe/feature_flags](http://localhos
52
56
 
53
57
  1. general usage, respecting only the environment
54
58
  ```rb
55
- FeatureFlag.enabled?(:flag)
59
+ Ffe::FeatureFlag.enabled?(:flag)
56
60
  # or
57
- FeatureFlag.disabled?(:flag)
61
+ Ffe::FeatureFlag.disabled?(:flag)
58
62
  ```
59
63
 
60
64
 
61
65
  2. check if a user is allowed
62
66
  ```rb
63
- FeatureFlag.enabled_for?(:flag, user: current_user)
67
+ Ffe::FeatureFlag.enabled_for?(:flag, user: current_user)
64
68
  ```
65
69
 
70
+ ## Usage Scenarios
71
+
72
+
73
+ **Use Case**: Cleaning-Up -- The functionality is available to everyone.
74
+
75
+ > Please don't forget to remove feature flags after its use isn't needed anymore.
76
+
77
+ > Every unused feature flag, makes the code noisy and uncomfortable to read and understand.
78
+
79
+ 1. Clean up the code after the feature flag has been disabled, or doesn't changed over a long time!
80
+
81
+ **Use Case**: A new functionality is to be developed that is accessible to specific users and/or environments via a feature flag.
82
+
83
+ 1. Create a feature flag in production
84
+ 2. Dump the flags, then replace the `config/feature_flags.json` file locally and commit it.
85
+ 3. Continue developing against the feature as before.
86
+
87
+ **Use Case**: Functionality is available to only a small number of users.
88
+
89
+ 1. Create a feature flag in production, and add allowed users.
90
+ 2. Dump the flags, then replace the `config/feature_flags.json` file locally and commit it.
91
+ 3. Edit the flag locally and specify a corresponding user.
92
+ 4. Continue developing against the feature as before.
93
+
94
+ **Use Case**: Set a feature flag for an announcement, or something similar, for a specific period of time.
95
+
96
+ > This requires the use of ActiveJob; currently, only `SolidQueue` and `Sidekiq` are supported. But feel free to add more.
97
+
98
+ 1. Create a feature flag in production, but without setting the expires date.
99
+ 2. Dump the flags, then replace the `config/feature_flags.json` file locally and commit it.
100
+ 3. Continue developing against the feature as before.
101
+ 4. After deployment to production, set the expiration date on the flag -- the flag will be automatically disabled after the expiration date.
102
+
66
103
 
67
104
  ## Contributing
68
105
 
@@ -5,19 +5,19 @@ module Ffe
5
5
  before_action :set_ffe, only: %i[show edit update destroy]
6
6
 
7
7
  def index
8
- @feature_flags = ::Ffe::FeatureFlag.order(created_at: :desc)
8
+ @feature_flags = Ffe::FeatureFlag.order(created_at: :desc)
9
9
  end
10
10
 
11
11
  def show; end
12
12
 
13
13
  def new
14
- @feature_flag = ::Ffe::FeatureFlag.new
14
+ @feature_flag = Ffe::FeatureFlag.new
15
15
  end
16
16
 
17
17
  def edit; end
18
18
 
19
19
  def create
20
- @feature_flag = ::Ffe::FeatureFlag.new(feature_flag_params.except(:milieus, :clear_expires_at))
20
+ @feature_flag = Ffe::FeatureFlag.new(feature_flag_params.except(:milieus, :clear_expires_at))
21
21
 
22
22
  if @feature_flag.save
23
23
  redirect_to feature_flag_path(@feature_flag), notice: 'FFE wurde erstellt.'
@@ -39,18 +39,23 @@ module Ffe
39
39
  redirect_to feature_flags_path, notice: 'FFE wurde gelöscht.'
40
40
  end
41
41
 
42
+ def dump
43
+ render json: Ffe::FeatureFlag.order(:name).map { |ff| ff.attributes.slice('name', 'description', 'enabled', 'milieu', 'expires_at', 'percentage') }
44
+ end
45
+
42
46
  private
43
47
 
44
48
  def set_ffe
45
- @feature_flag = ::Ffe::FeatureFlag.find(params.expect(:id))
49
+ @feature_flag = Ffe::FeatureFlag.find(params.expect(:id))
46
50
  end
47
51
 
48
52
  def feature_flag_params
49
53
  params.expect(
50
- feature_flag: [:name, :description, :enabled, :expires_at, :clear_expires_at, { milieus: {} }]
54
+ feature_flag: [:name, :description, :enabled, :expires_at, :clear_expires_at, { user_ids: [], milieus: {} }]
51
55
  ).tap do |params|
52
56
  params[:milieu] = params[:milieus].values.join.ljust(Ffe.config.bitlength, '0') if params[:milieus].present?
53
57
  params[:expires_at] = nil if params[:clear_expires_at] == '1'
58
+ params[:user_ids]&.delete_if(&:blank?)
54
59
  end
55
60
  end
56
61
  end
@@ -43,6 +43,11 @@
43
43
  <% end %>
44
44
  </div>
45
45
 
46
+ <div>
47
+ <%= form.label :user_ids %>
48
+ <%= form.collection_select :user_ids, Ffe::User.all, :id, :name, { include_blank: true, multiple: true } %>
49
+ </div>
50
+
46
51
  <div>
47
52
  <%= form.submit %>
48
53
  </div>
@@ -1,6 +1,7 @@
1
1
  <h1>Feature Flags</h1>
2
2
 
3
- <p><%= link_to "Neues Feature Flag anlegen", new_feature_flag_path %></p>
3
+ <div><%= link_to 'Neues Feature Flag anlegen', new_feature_flag_path %></div>
4
+ <div><%= link_to 'dump', dump_feature_flags_path, download: 'feature_flags.json' %></div>
4
5
 
5
6
  <table>
6
7
  <thead>
@@ -22,8 +23,8 @@
22
23
  <td><%= feature_flag.expires_at&.strftime('%Y-%m-%dT%H:%M') %></td>
23
24
  <td><%= feature_flag.readable_milieus %></td>
24
25
  <td>
25
- <%= link_to "Bearbeiten", edit_feature_flag_path(feature_flag) %>
26
- <%= button_to "Löschen", feature_flag_path(feature_flag), method: :delete %>
26
+ <%= link_to 'Bearbeiten', edit_feature_flag_path(feature_flag) %>
27
+ <%= button_to 'Löschen', feature_flag_path(feature_flag), method: :delete %>
27
28
  </td>
28
29
  </tr>
29
30
  <% end %>
@@ -17,5 +17,10 @@
17
17
  <%= @feature_flag.readable_milieus %>
18
18
  </div>
19
19
 
20
+ <div>
21
+ <strong>User IDs:</strong>
22
+ <%= @feature_flag.user_ids %>
23
+ </div>
24
+
20
25
  <p><%= link_to "Bearbeiten", edit_feature_flag_path(@feature_flag) %></p>
21
26
  <p><%= link_to "Zurück", feature_flags_path %></p>
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  Ffe::Engine.routes.draw do
2
- resources :feature_flags
2
+ resources :feature_flags do
3
+ get :dump, on: :collection
4
+ end
3
5
  end
data/lib/ffe/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ffe
4
- VERSION = '0.2.0'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -11,6 +11,7 @@ module Ffe
11
11
 
12
12
  def copy_initializer
13
13
  template 'ffe_initializer.rb.tt', 'config/initializers/ffe.rb'
14
+ template 'feature_flags.json.tt', 'config/feature_flags.json'
14
15
  end
15
16
  end
16
17
  end
@@ -0,0 +1,9 @@
1
+ [
2
+ {
3
+ "name": "x_dummy_testing",
4
+ "description": "A general testing FF.",
5
+ "enabled": true,
6
+ "milieu": "1000",
7
+ "expires_at": null,
8
+ }
9
+ ]
@@ -29,3 +29,19 @@ Ffe.configure do |config|
29
29
  # actual supported: :solid_queue, :sidekiq
30
30
  config.queue_adapter = ActiveJob::Base.queue_adapter_name.to_sym
31
31
  end
32
+
33
+
34
+ Rails.configuration.after_initialize do
35
+ if ActiveRecord::Base.connection.table_exists?(:feature_flags)
36
+ path = Rails.root.join('config/feature_flags.json')
37
+ next unless File.exist?(path)
38
+
39
+ data = JSON.load_file(path)
40
+ data.each do |flag|
41
+ name = flag.delete('name')
42
+ next if Ffe::FeatureFlag.exists?(name: name)
43
+
44
+ Ffe::FeatureFlag.create_with(flag).find_or_create_by(name: name)
45
+ end
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LeFnord
@@ -59,6 +59,7 @@ files:
59
59
  - lib/ffe/engine.rb
60
60
  - lib/ffe/version.rb
61
61
  - lib/generators/ffe/install/install_generator.rb
62
+ - lib/generators/ffe/templates/feature_flags.json.tt
62
63
  - lib/generators/ffe/templates/ffe_initializer.rb.tt
63
64
  - lib/tasks/ffe_tasks.rake
64
65
  homepage: https://github.com/LeFnord/ffe