ffe 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +43 -0
- data/Rakefile +8 -0
- data/app/assets/stylesheets/ffe/application.css +15 -0
- data/app/controllers/ffe/application_controller.rb +6 -0
- data/app/controllers/ffe/feature_flags_controller.rb +54 -0
- data/app/helpers/ffe/application_helper.rb +6 -0
- data/app/jobs/ffe/application_job.rb +6 -0
- data/app/mailers/ffe/application_mailer.rb +8 -0
- data/app/models/ffe/application_record.rb +7 -0
- data/app/models/ffe/feature_flag.rb +51 -0
- data/app/models/ffe/user.rb +9 -0
- data/app/views/ffe/feature_flags/_form.html.erb +47 -0
- data/app/views/ffe/feature_flags/edit.html.erb +5 -0
- data/app/views/ffe/feature_flags/index.html.erb +31 -0
- data/app/views/ffe/feature_flags/new.html.erb +5 -0
- data/app/views/ffe/feature_flags/show.html.erb +21 -0
- data/app/views/layouts/ffe/application.html.erb +17 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20260810150000_create_feature_flags.rb +17 -0
- data/db/migrate/20260814160209_create_users.rb +11 -0
- data/lib/ffe/configuration.rb +13 -0
- data/lib/ffe/engine.rb +9 -0
- data/lib/ffe/version.rb +5 -0
- data/lib/ffe.rb +17 -0
- data/lib/generators/ffe/install/install_generator.rb +17 -0
- data/lib/generators/ffe/templates/ffe_initializer.rb.tt +26 -0
- data/lib/tasks/ffe_tasks.rake +6 -0
- metadata +86 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e4a4f8d7608dddb3df97d2e03b69b815cfd23662ef1f3eb83a934f5336a63b73
|
|
4
|
+
data.tar.gz: fb39e4b322a411d8e93f29b0cdaefc27b12fc3c418efde0a74198e5301f51806
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d3cdfbfc53a7015ceefed64e5c6ac7bfe364beea2f33e874ee946b0245ca7f90bc198c45a17fa77ab7be87b8b0e89395b91f6e73f2c2258077669942ea7758cb
|
|
7
|
+
data.tar.gz: 6a7060e5583b18bf30e218663ea19bd7cd6f93fba0541c39d2a0015be3847b57d608befd54313482d3f3e54e0184a6181caa40970334fbd40bcb2712bca30fb0
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright LeFnord
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Ffe
|
|
2
|
+
|
|
3
|
+
A minimalistic Feature Flag engine, cause i was bored of unleash and other overloaded ones.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
Add this line to your application's Gemfile:
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
gem "ffe"
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
And then execute:
|
|
13
|
+
```bash
|
|
14
|
+
$ bundle install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Copy over the initializer with:
|
|
18
|
+
```bash
|
|
19
|
+
$ bin/rails g ffe:install
|
|
20
|
+
```
|
|
21
|
+
and adjust it to your needs.
|
|
22
|
+
|
|
23
|
+
Install the migration with:
|
|
24
|
+
```bash
|
|
25
|
+
$ bin/rails ffe:install:migrations
|
|
26
|
+
```
|
|
27
|
+
(have an eye on the length of the `milieu` bit mask)
|
|
28
|
+
|
|
29
|
+
Mount the engine in your application's `config/routes.rb` file:
|
|
30
|
+
```ruby
|
|
31
|
+
mount Ffe::Engine => "/feature_flags"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
coming soon
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## Contributing
|
|
40
|
+
Contribution directions go here.
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
|
11
|
+
* It is generally better to create a new file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ffe
|
|
4
|
+
class FeatureFlagsController < ApplicationController
|
|
5
|
+
before_action :set_ffe, only: %i[show edit update destroy]
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@feature_flags = ::Ffe::FeatureFlag.order(created_at: :desc)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def show; end
|
|
12
|
+
|
|
13
|
+
def new
|
|
14
|
+
@feature_flag = ::Ffe::FeatureFlag.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def edit; end
|
|
18
|
+
|
|
19
|
+
def create
|
|
20
|
+
@feature_flag = ::Ffe::FeatureFlag.new(feature_flag_params.except(:milieus))
|
|
21
|
+
|
|
22
|
+
if @feature_flag.save
|
|
23
|
+
redirect_to feature_flag_path(@feature_flag), notice: 'FFE wurde erstellt.'
|
|
24
|
+
else
|
|
25
|
+
render :new, status: :unprocessable_content
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def update
|
|
30
|
+
if @feature_flag.update(feature_flag_params.except(:milieus))
|
|
31
|
+
redirect_to feature_flag_path(@feature_flag), notice: 'FFE wurde aktualisiert.'
|
|
32
|
+
else
|
|
33
|
+
render :edit, status: :unprocessable_content
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def destroy
|
|
38
|
+
@feature_flag.destroy
|
|
39
|
+
redirect_to feature_flags_path, notice: 'FFE wurde gelöscht.'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def set_ffe
|
|
45
|
+
@feature_flag = ::Ffe::FeatureFlag.find(params.expect(:id))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def feature_flag_params
|
|
49
|
+
params.expect(feature_flag: [:name, :description, :enabled, :expires_at, { milieus: {} }]).tap do |params|
|
|
50
|
+
params[:milieu] = params[:milieus].values.join.ljust(Ffe.config.bitlength, '0') if params[:milieus].present?
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ffe
|
|
4
|
+
class FeatureFlag < ApplicationRecord
|
|
5
|
+
self.table_name = 'feature_flags'
|
|
6
|
+
|
|
7
|
+
validates :name, presence: true, uniqueness: true, format: { with: /\A[a-zA-Z_]+\z/ }
|
|
8
|
+
validates :expires_at, comparison: { greater_than: Time.current.end_of_day }, if: -> { expires_at.present? }
|
|
9
|
+
|
|
10
|
+
# the Flag functionality itself
|
|
11
|
+
#
|
|
12
|
+
# main methods
|
|
13
|
+
def self.enabled?(flag)
|
|
14
|
+
feature = find_by(name: flag)
|
|
15
|
+
|
|
16
|
+
feature.enabled? && feature.allowed_milieu?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.disabled?(flag)
|
|
20
|
+
!enabled?(flag)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.enabled_for?(flag, user: nil)
|
|
24
|
+
return enabled?(flag) if user.blank?
|
|
25
|
+
|
|
26
|
+
feature = find_by(name: flag)
|
|
27
|
+
return false unless feature.allowed_milieu?
|
|
28
|
+
|
|
29
|
+
feature.enabled? && feature.user_ids.include?(user.id.to_s)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# instance methods
|
|
33
|
+
#
|
|
34
|
+
def allowed_milieu?
|
|
35
|
+
actual_milieu = ENV.fetch(Ffe.config.env_variable, false)
|
|
36
|
+
return false unless actual_milieu
|
|
37
|
+
|
|
38
|
+
pos = Ffe.config.milieus[actual_milieu.to_sym]
|
|
39
|
+
milieu[pos] == '1'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def readable_milieus # rubocop:disable Metrics/AbcSize
|
|
43
|
+
relevant = milieu.to_s.ljust(Ffe.config.milieus.length, '0').chars.first(Ffe.config.milieus.length)
|
|
44
|
+
return 'all' if relevant.all? { |m| m == '1' }
|
|
45
|
+
return 'no' if relevant.all? { |m| m == '0' }
|
|
46
|
+
|
|
47
|
+
inverted = Ffe.config.milieus.invert
|
|
48
|
+
relevant.each_with_index.filter_map { |m, i| inverted[i] if m == '1' }.join(', ')
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<%= form_with model: feature_flag do |form| %>
|
|
2
|
+
<% if feature_flag.errors.any? %>
|
|
3
|
+
<div>
|
|
4
|
+
<h2><%= pluralize(feature_flag.errors.count, "Fehler") %> verhindert das Speichern:</h2>
|
|
5
|
+
<ul>
|
|
6
|
+
<% feature_flag.errors.full_messages.each do |message| %>
|
|
7
|
+
<li><%= message %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
</ul>
|
|
10
|
+
</div>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<div>
|
|
14
|
+
<%= form.label :name %>
|
|
15
|
+
<%= form.text_field :name %>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div>
|
|
19
|
+
<%= form.label :description %>
|
|
20
|
+
<%= form.text_field :description %>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div>
|
|
24
|
+
<%= form.label :enabled %>
|
|
25
|
+
<%= form.check_box :enabled %>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div>
|
|
29
|
+
<%= form.label :expires_at %>
|
|
30
|
+
<%= form.datetime_local_field :expires_at, min: Time.current.tomorrow.beginning_of_day, value: feature_flag.expires_at&.strftime('%Y-%m-%dT%H:%M') %>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div>
|
|
34
|
+
<%= form.fields_for :milieus do |milieu| %>
|
|
35
|
+
<%- Ffe.config.milieus.each do |(env, pos)| %>
|
|
36
|
+
<div>
|
|
37
|
+
<%= milieu.label env %>
|
|
38
|
+
<%= milieu.check_box env, checked: feature_flag.milieu[pos] == '1' %>
|
|
39
|
+
</div>
|
|
40
|
+
<% end %>
|
|
41
|
+
<% end %>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div>
|
|
45
|
+
<%= form.submit %>
|
|
46
|
+
</div>
|
|
47
|
+
<% end %>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<h1>Feature Flags</h1>
|
|
2
|
+
|
|
3
|
+
<p><%= link_to "Neues Feature Flag anlegen", new_feature_flag_path %></p>
|
|
4
|
+
|
|
5
|
+
<table>
|
|
6
|
+
<thead>
|
|
7
|
+
<tr>
|
|
8
|
+
<th>Name</th>
|
|
9
|
+
<th>Description</th>
|
|
10
|
+
<th>Enabled</th>
|
|
11
|
+
<th>Expires At</th>
|
|
12
|
+
<th>Environments</th>
|
|
13
|
+
<th>Actions</th>
|
|
14
|
+
</tr>
|
|
15
|
+
</thead>
|
|
16
|
+
<tbody>
|
|
17
|
+
<% @feature_flags.each do |feature_flag| %>
|
|
18
|
+
<tr>
|
|
19
|
+
<td><%= link_to feature_flag.name, feature_flag_path(feature_flag) %></td>
|
|
20
|
+
<td><%= feature_flag.description %></td>
|
|
21
|
+
<td><%= feature_flag.enabled %></td>
|
|
22
|
+
<td><%= feature_flag.expires_at&.strftime('%Y-%m-%dT%H:%M') %></td>
|
|
23
|
+
<td><%= feature_flag.readable_milieus %></td>
|
|
24
|
+
<td>
|
|
25
|
+
<%= link_to "Bearbeiten", edit_feature_flag_path(feature_flag) %>
|
|
26
|
+
<%= button_to "Löschen", feature_flag_path(feature_flag), method: :delete %>
|
|
27
|
+
</td>
|
|
28
|
+
</tr>
|
|
29
|
+
<% end %>
|
|
30
|
+
</tbody>
|
|
31
|
+
</table>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<h1><%= @feature_flag.name %></h1>
|
|
2
|
+
|
|
3
|
+
<div>
|
|
4
|
+
<strong>Description:</strong>
|
|
5
|
+
<%= @feature_flag.description %>
|
|
6
|
+
</div>
|
|
7
|
+
<div>
|
|
8
|
+
<strong>Enabled:</strong>
|
|
9
|
+
<%= @feature_flag.enabled %>
|
|
10
|
+
</div>
|
|
11
|
+
<div>
|
|
12
|
+
<strong>Expires at:</strong>
|
|
13
|
+
<%= @feature_flag.expires_at&.strftime('%Y-%m-%dT%H:%M') %>
|
|
14
|
+
</div>
|
|
15
|
+
<div>
|
|
16
|
+
<strong>Milieus:</strong>
|
|
17
|
+
<%= @feature_flag.readable_milieus %>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<p><%= link_to "Bearbeiten", edit_feature_flag_path(@feature_flag) %></p>
|
|
21
|
+
<p><%= link_to "Zurück", feature_flags_path %></p>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Ffe</title>
|
|
5
|
+
<%= csrf_meta_tags %>
|
|
6
|
+
<%= csp_meta_tag %>
|
|
7
|
+
|
|
8
|
+
<%= yield :head %>
|
|
9
|
+
|
|
10
|
+
<%= stylesheet_link_tag "ffe/application", media: "all" %>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<%= yield %>
|
|
15
|
+
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class CreateFeatureFlags < ActiveRecord::Migration[8.2]
|
|
2
|
+
def change
|
|
3
|
+
create_table :feature_flags do |t|
|
|
4
|
+
t.string :name, null: false
|
|
5
|
+
t.string :description
|
|
6
|
+
t.boolean :enabled, default: false
|
|
7
|
+
t.datetime :expires_at
|
|
8
|
+
t.column :milieu, "bit(#{Ffe.config.bitlength})", default: ''.ljust(Ffe.config.bitlength, '0') # only for PG
|
|
9
|
+
t.text :user_ids, array: true, default: []
|
|
10
|
+
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
add_index :feature_flags, :name, unique: true
|
|
15
|
+
add_index :feature_flags, :user_ids, using: :gin
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ffe
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_accessor :bitlength, :env_variable, :milieus
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@bitlength = 4
|
|
9
|
+
@env_variable = 'RAILS_ENV'
|
|
10
|
+
@milieus = { development: 0, staging: 1, production: 2 }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/ffe/engine.rb
ADDED
data/lib/ffe/version.rb
ADDED
data/lib/ffe.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ffe/version'
|
|
4
|
+
require 'ffe/configuration'
|
|
5
|
+
require 'ffe/engine'
|
|
6
|
+
|
|
7
|
+
module Ffe
|
|
8
|
+
class << self
|
|
9
|
+
def configure
|
|
10
|
+
yield config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def config
|
|
14
|
+
Rails.application.config.ffe
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module Ffe
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path('../templates', __dir__)
|
|
9
|
+
|
|
10
|
+
desc 'Creates an initializer for the Ffe engine'
|
|
11
|
+
|
|
12
|
+
def copy_initializer
|
|
13
|
+
template 'ffe_initializer.rb.tt', 'config/initializers/ffe.rb'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Ffe.configure do |config|
|
|
4
|
+
# Configure the Ffe engine here.
|
|
5
|
+
# (given values are the defaults)
|
|
6
|
+
|
|
7
|
+
# configure the length of the bitmask, used to store the milieus,
|
|
8
|
+
# the minimum length should be length of milieus
|
|
9
|
+
config.bitlength = 4
|
|
10
|
+
|
|
11
|
+
# define the environments you want to use,
|
|
12
|
+
# the count of items maps directly to the length of the milieu bit mask above,
|
|
13
|
+
# so change it accordingly
|
|
14
|
+
#
|
|
15
|
+
# for example: add a fourth environment
|
|
16
|
+
# config.milieus = { development: 0, staging: 1, production: 2, testing: 3}
|
|
17
|
+
# the minimum bitlength becomes:
|
|
18
|
+
# config.bitlength = 4
|
|
19
|
+
#
|
|
20
|
+
# (later changes are bit more complicated, so increase the bit length before)
|
|
21
|
+
#
|
|
22
|
+
config.milieus = { development: 0, staging: 1, production: 2 }
|
|
23
|
+
|
|
24
|
+
# not all rails apps are using RAILS_ENV variable to set it
|
|
25
|
+
config.env_variable = 'RAILS_ENV'
|
|
26
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ffe
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- LeFnord
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '8.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '8.0'
|
|
26
|
+
description: A minimal Feature Flag Engine for Rails.
|
|
27
|
+
email:
|
|
28
|
+
- pscholz.le@gmail.com
|
|
29
|
+
executables: []
|
|
30
|
+
extensions: []
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
files:
|
|
33
|
+
- MIT-LICENSE
|
|
34
|
+
- README.md
|
|
35
|
+
- Rakefile
|
|
36
|
+
- app/assets/stylesheets/ffe/application.css
|
|
37
|
+
- app/controllers/ffe/application_controller.rb
|
|
38
|
+
- app/controllers/ffe/feature_flags_controller.rb
|
|
39
|
+
- app/helpers/ffe/application_helper.rb
|
|
40
|
+
- app/jobs/ffe/application_job.rb
|
|
41
|
+
- app/mailers/ffe/application_mailer.rb
|
|
42
|
+
- app/models/ffe/application_record.rb
|
|
43
|
+
- app/models/ffe/feature_flag.rb
|
|
44
|
+
- app/models/ffe/user.rb
|
|
45
|
+
- app/views/ffe/feature_flags/_form.html.erb
|
|
46
|
+
- app/views/ffe/feature_flags/edit.html.erb
|
|
47
|
+
- app/views/ffe/feature_flags/index.html.erb
|
|
48
|
+
- app/views/ffe/feature_flags/new.html.erb
|
|
49
|
+
- app/views/ffe/feature_flags/show.html.erb
|
|
50
|
+
- app/views/layouts/ffe/application.html.erb
|
|
51
|
+
- config/routes.rb
|
|
52
|
+
- db/migrate/20260810150000_create_feature_flags.rb
|
|
53
|
+
- db/migrate/20260814160209_create_users.rb
|
|
54
|
+
- lib/ffe.rb
|
|
55
|
+
- lib/ffe/configuration.rb
|
|
56
|
+
- lib/ffe/engine.rb
|
|
57
|
+
- lib/ffe/version.rb
|
|
58
|
+
- lib/generators/ffe/install/install_generator.rb
|
|
59
|
+
- lib/generators/ffe/templates/ffe_initializer.rb.tt
|
|
60
|
+
- lib/tasks/ffe_tasks.rake
|
|
61
|
+
homepage: https://github.com/LeFnord/ffe
|
|
62
|
+
licenses:
|
|
63
|
+
- MIT
|
|
64
|
+
metadata:
|
|
65
|
+
homepage_uri: https://github.com/LeFnord/ffe
|
|
66
|
+
source_code_uri: https://github.com/LeFnord/ffe
|
|
67
|
+
changelog_uri: https://github.com/LeFnord/ffe/blob/master/CHANGELOG.md
|
|
68
|
+
rubygems_mfa_required: 'true'
|
|
69
|
+
rdoc_options: []
|
|
70
|
+
require_paths:
|
|
71
|
+
- lib
|
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '4.0'
|
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
requirements: []
|
|
83
|
+
rubygems_version: 4.0.18
|
|
84
|
+
specification_version: 4
|
|
85
|
+
summary: A minimal Feature Flag Engine for Rails
|
|
86
|
+
test_files: []
|