rails_flags 0.1.0 → 0.1.1

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: fd89ec7b4bef50b03eeda197bffb23d1f88da83dfd91e7e68d18f65643b46c46
4
- data.tar.gz: b3fe66c98c53b2f07e10460a08d8853f4e2f62d79ca37f20eb2b66c2d453a6ea
3
+ metadata.gz: fe7b819caaddc037424b3b33e788af96fa02da82f94c6ec2b60c7fe99431e886
4
+ data.tar.gz: d68835ff9af94c371e65bc0d4b35386d67f9e749cb61a7818dfc7e8abc0900d8
5
5
  SHA512:
6
- metadata.gz: 39f075f0e4bd50afffcb40f53a6130b535151c0e8cfcf1f60dc3bc265ef82e84b2393ca2457cfe54dc7b1a32728501593cc792267c3d0269e121cd3032ecc7c5
7
- data.tar.gz: 3da159ab062c096037bda7c92a38696fd987c6fde0209dc5206885e3f71bc22f13cbf8a6f9d5c5f00649b28d3d6a976c1c52ecf692037b5400c8fb957b9c1c2a
6
+ metadata.gz: 2b9893919d8d482e8c2b9b0ecebde2dbdd2c0c62fffc9597962e9aeb89ce9cb74eb6d1a988e98d7aa67cb8ff55446fa6987d4b48821a2c50116d3ebf4a9335f1
7
+ data.tar.gz: 30c12444f5b1d0464e8a4e479cb648e8ecc3910574faa68700bd47393de218ff4f3912cd44ad022e46e889187ed88609be4d08f05977decf0f1f272eafed9821
data/README.md CHANGED
@@ -9,6 +9,7 @@ A simple and powerful feature flagging system for Ruby on Rails applications. Ra
9
9
  - Thread-safe operations
10
10
  - Configurable default states
11
11
  - Support for flag metadata (descriptions, creation timestamps)
12
+ - Built-in admin interface for managing feature flags
12
13
 
13
14
  ## Installation
14
15
 
@@ -46,7 +47,28 @@ RailsFlags.configure do |config|
46
47
  end
47
48
  ```
48
49
 
49
- ### Registering Flags
50
+ ## Usage
51
+
52
+ ### Mounting the Engine
53
+ Add this to your `config/routes.rb`:
54
+ ```ruby
55
+ Rails.application.routes.draw do
56
+ mount RailsFlags::Engine => "/rails_flags"
57
+ end
58
+ ```
59
+
60
+ ### Admin Interface
61
+ Access the admin interface at `/rails_flags/admin` to:
62
+ - View all feature flags
63
+ - Create new feature flags
64
+ - Enable/disable flags
65
+ - Delete feature flags
66
+
67
+ ![RailsFlags](docs/images/dashboard.png)
68
+
69
+ ### Programmatic Usage
70
+
71
+ #### Registering Flags
50
72
  ```ruby
51
73
  # Register a new feature flag (disabled by default)
52
74
  RailsFlags.register(
@@ -63,7 +85,7 @@ RailsFlags.register(
63
85
  )
64
86
  ```
65
87
 
66
- ### Checking Flags
88
+ #### Checking Flags
67
89
  ```ruby
68
90
  # Check if a flag is enabled
69
91
  if RailsFlags.enabled?(:new_feature)
@@ -74,7 +96,7 @@ end
74
96
  RailsFlags.registered?(:new_feature)
75
97
  ```
76
98
 
77
- ### Managing Flags
99
+ #### Managing Flags
78
100
  ```ruby
79
101
  # Enable a flag
80
102
  RailsFlags.enable(:new_feature)
@@ -82,10 +104,21 @@ RailsFlags.enable(:new_feature)
82
104
  # Disable a flag
83
105
  RailsFlags.disable(:new_feature)
84
106
 
107
+ # Delete a flag
108
+ RailsFlags.delete(:new_feature)
109
+
85
110
  # Get all flags
86
111
  all_flags = RailsFlags.all_flags
87
112
  ```
88
113
 
114
+ ### In Views
115
+ You can use feature flags in your views:
116
+ ```erb
117
+ <% if RailsFlags.enabled?(:new_feature) %>
118
+ <!-- New feature content -->
119
+ <% end %>
120
+ ```
121
+
89
122
  ## Storage Adapters
90
123
 
91
124
  ### Memory Adapter
@@ -99,6 +132,23 @@ all_flags = RailsFlags.all_flags
99
132
  - Provides atomic operations
100
133
  - Requires Redis server
101
134
 
135
+ ## Testing
136
+
137
+ This gem supports multiple Rails versions (6.x, 7.x, and 8.x). We use Appraisal to test against different Rails versions.
138
+
139
+ To run the tests for all supported Rails versions:
140
+
141
+ ```bash
142
+ bundle exec appraisal rspec
143
+ ```
144
+
145
+ To run tests for a specific Rails version:
146
+
147
+ ```bash
148
+ bundle exec appraisal rails-6 rspec # For Rails 6
149
+ bundle exec appraisal rails-7 rspec # For Rails 7
150
+ bundle exec appraisal rails-8 rspec # For Rails 8
151
+ ```
102
152
 
103
153
  ## Contributing
104
154
 
@@ -0,0 +1,36 @@
1
+ module RailsFlags
2
+ class AdminController < ApplicationController
3
+ def index
4
+ @feature_flags = RailsFlags.all_flags
5
+ end
6
+
7
+ def create
8
+ RailsFlags.register(
9
+ params[:name],
10
+ enabled: params[:enabled] == "1",
11
+ description: params[:description]
12
+ )
13
+ redirect_to admin_path, notice: "Feature flag created successfully"
14
+ rescue StandardError => e
15
+ redirect_to admin_path, alert: e.message
16
+ end
17
+
18
+ def update
19
+ if params[:enabled] == "1"
20
+ RailsFlags.enable(params[:name])
21
+ else
22
+ RailsFlags.disable(params[:name])
23
+ end
24
+ redirect_to admin_path, notice: "Feature flag updated successfully"
25
+ rescue StandardError => e
26
+ redirect_to admin_path, alert: e.message
27
+ end
28
+
29
+ def destroy
30
+ RailsFlags.delete(params[:name])
31
+ redirect_to admin_path, notice: "Feature flag deleted successfully"
32
+ rescue StandardError => e
33
+ redirect_to admin_path, alert: e.message
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,101 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Feature Flags Admin</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <%= csrf_meta_tags %>
7
+ <%= csp_meta_tag %>
8
+
9
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
10
+ </head>
11
+ <body>
12
+ <div class="container mt-4">
13
+ <h1>Feature Flags Admin</h1>
14
+
15
+ <% if notice %>
16
+ <div class="alert alert-success"><%= notice %></div>
17
+ <% end %>
18
+
19
+ <% if alert %>
20
+ <div class="alert alert-danger"><%= alert %></div>
21
+ <% end %>
22
+
23
+ <!-- New Feature Flag Form -->
24
+ <div class="card mb-4">
25
+ <div class="card-header">
26
+ <h5 class="mb-0">Create New Feature Flag</h5>
27
+ </div>
28
+ <div class="card-body">
29
+ <%= form_tag admin_create_path, method: :post, class: 'row g-3' do %>
30
+ <div class="col-md-4">
31
+ <label class="form-label">Name</label>
32
+ <%= text_field_tag :name, nil, class: 'form-control', required: true %>
33
+ </div>
34
+ <div class="col-md-6">
35
+ <label class="form-label">Description</label>
36
+ <%= text_field_tag :description, nil, class: 'form-control' %>
37
+ </div>
38
+ <div class="col-md-2">
39
+ <label class="form-label">Enabled</label>
40
+ <div>
41
+ <%= check_box_tag :enabled, "1", false, class: 'form-check-input' %>
42
+ </div>
43
+ </div>
44
+ <div class="col-12">
45
+ <%= submit_tag 'Create Feature Flag', class: 'btn btn-primary' %>
46
+ </div>
47
+ <% end %>
48
+ </div>
49
+ </div>
50
+
51
+ <!-- Feature Flags List -->
52
+ <div class="card">
53
+ <div class="card-header">
54
+ <h5 class="mb-0">Existing Feature Flags</h5>
55
+ </div>
56
+ <div class="card-body">
57
+ <div class="table-responsive">
58
+ <table class="table">
59
+ <thead>
60
+ <tr>
61
+ <th>Name</th>
62
+ <th>Description</th>
63
+ <th>Status</th>
64
+ <th>Created At</th>
65
+ <th>Actions</th>
66
+ </tr>
67
+ </thead>
68
+ <tbody>
69
+ <% @feature_flags.each do |name, data| %>
70
+ <tr>
71
+ <td><%= name %></td>
72
+ <td><%= data[:description] %></td>
73
+ <td>
74
+ <%= form_tag admin_update_path(name), method: :patch, class: 'd-inline' do %>
75
+ <div class="form-check form-switch">
76
+ <%= check_box_tag :enabled, "1", data[:enabled],
77
+ class: 'form-check-input',
78
+ onchange: 'this.form.submit()' %>
79
+ </div>
80
+ <% end %>
81
+ </td>
82
+ <td><%= data[:created_at]&.strftime("%Y-%m-%d %H:%M:%S") %></td>
83
+ <td>
84
+ <%= button_to "Delete",
85
+ admin_delete_path(name),
86
+ method: :delete,
87
+ class: "btn btn-danger btn-sm",
88
+ data: { confirm: "Are you sure?" } %>
89
+ </td>
90
+ </tr>
91
+ <% end %>
92
+ </tbody>
93
+ </table>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
100
+ </body>
101
+ </html>
data/config/routes.rb CHANGED
@@ -1,2 +1,8 @@
1
1
  RailsFlags::Engine.routes.draw do
2
+ get "/admin", to: "admin#index", as: :admin
3
+ post "/admin/create", to: "admin#create", as: :admin_create
4
+ patch "/admin/:name", to: "admin#update", as: :admin_update
5
+ delete "/admin/:name", to: "admin#destroy", as: :admin_delete
6
+
7
+ root to: "admin#index"
2
8
  end
@@ -42,6 +42,11 @@ module RailsFlags
42
42
  @adapter.write(flag.to_sym, data)
43
43
  end
44
44
 
45
+ def delete(flag)
46
+ validate_flag_exists!(flag)
47
+ @adapter.delete(flag.to_sym)
48
+ end
49
+
45
50
  def registered?(flag)
46
51
  @adapter.read(flag.to_sym) ? true : false
47
52
  end
@@ -53,7 +58,8 @@ module RailsFlags
53
58
  private
54
59
 
55
60
  def validate_flag_name!(name)
56
- raise ArgumentError, "Flag name must be a String or Symbol" unless name.is_a?(String) || name.is_a?(Symbol)
61
+ raise ArgumentError, "Flag name cannot be nil" if name.nil?
62
+ raise ArgumentError, "Flag name must be a string or symbol" unless name.is_a?(String) || name.is_a?(Symbol)
57
63
  raise ArgumentError, "Flag name cannot be empty" if name.to_s.strip.empty?
58
64
  end
59
65
 
@@ -1,3 +1,3 @@
1
1
  module RailsFlags
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/rails_flags.rb CHANGED
@@ -19,6 +19,10 @@ module RailsFlags
19
19
  configuration.register(flag_name, **options)
20
20
  end
21
21
 
22
+ def delete(flag_name)
23
+ configuration.delete(flag_name)
24
+ end
25
+
22
26
  def enabled?(flag)
23
27
  configuration.enabled?(flag)
24
28
  rescue KeyError => e
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_flags
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dhurba Baral
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 8.0.0
19
+ version: '6.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '8.1'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: 8.0.0
29
+ version: '6.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '8.1'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: redis
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +58,20 @@ dependencies:
52
58
  - - ">="
53
59
  - !ruby/object:Gem::Version
54
60
  version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: appraisal
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
55
75
  description: A simple and powerful feature flagging system for Ruby on Rails applications.
56
76
  RailsFlags provides an easy way to manage feature flags with support for multiple
57
77
  storage backends.
@@ -65,12 +85,14 @@ files:
65
85
  - README.md
66
86
  - Rakefile
67
87
  - app/assets/stylesheets/rails_flags/application.css
88
+ - app/controllers/rails_flags/admin_controller.rb
68
89
  - app/controllers/rails_flags/application_controller.rb
69
90
  - app/helpers/rails_flags/application_helper.rb
70
91
  - app/jobs/rails_flags/application_job.rb
71
92
  - app/mailers/rails_flags/application_mailer.rb
72
93
  - app/models/rails_flags/application_record.rb
73
94
  - app/views/layouts/rails_flags/application.html.erb
95
+ - app/views/rails_flags/admin/index.html.erb
74
96
  - config/routes.rb
75
97
  - lib/rails_flags.rb
76
98
  - lib/rails_flags/adapters/base.rb