arturo 2.1.0 → 4.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 +5 -5
- data/CHANGELOG.md +90 -0
- data/README.md +142 -93
- data/app/controllers/arturo/features_controller.rb +6 -13
- data/app/helpers/arturo/features_helper.rb +1 -0
- data/app/views/arturo/features/_feature.html.erb +1 -0
- data/app/views/arturo/features/_form.html.erb +1 -0
- data/app/views/arturo/features/edit.html.erb +1 -0
- data/app/views/arturo/features/forbidden.html.erb +1 -0
- data/app/views/arturo/features/index.html.erb +1 -0
- data/app/views/arturo/features/new.html.erb +1 -0
- data/app/views/arturo/features/show.html.erb +1 -0
- data/config/locales/en.yml +1 -1
- data/config/routes.rb +4 -12
- data/lib/arturo/controller_filters.rb +3 -2
- data/lib/arturo/engine.rb +2 -8
- data/lib/arturo/feature_availability.rb +2 -1
- data/lib/arturo/feature_caching.rb +118 -23
- data/lib/arturo/feature_factories.rb +3 -2
- data/lib/arturo/feature_management.rb +1 -0
- data/lib/arturo/feature_methods.rb +95 -0
- data/lib/arturo/feature_params_support.rb +6 -4
- data/lib/arturo/middleware.rb +1 -0
- data/lib/arturo/no_such_feature.rb +1 -0
- data/lib/arturo/null_logger.rb +8 -0
- data/lib/arturo/special_handling.rb +6 -6
- data/lib/arturo/test_support.rb +3 -2
- data/lib/arturo/version.rb +4 -0
- data/lib/arturo.rb +28 -6
- data/lib/generators/arturo/assets_generator.rb +1 -0
- data/lib/generators/arturo/feature_model_generator.rb +14 -0
- data/lib/generators/arturo/initializer_generator.rb +1 -0
- data/lib/generators/arturo/migration_generator.rb +10 -10
- data/lib/generators/arturo/routes_generator.rb +1 -0
- data/lib/generators/arturo/templates/feature.rb +9 -0
- data/lib/generators/arturo/templates/initializer.rb +1 -0
- data/lib/generators/arturo/templates/migration.erb +17 -0
- metadata +36 -200
- data/lib/arturo/feature.rb +0 -90
- data/lib/generators/arturo/templates/migration.rb +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f3dd4873bb989ef7051937ac1b4ba16a49cc5691cc920d51b6714f330cd6b191
|
|
4
|
+
data.tar.gz: 0e8dfa652180dcba96d51779fa5734a128f1233b01467c4d77f79b80dadfcc23
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f8df1180d466898b1f0992e15fedf692769cee73a52efcd6d905d0ec9a09d2f69eb7a69a847e9a724ec8ab25ef01c8417f9854a0400ddc222efc5fa0583fe83
|
|
7
|
+
data.tar.gz: 719901f7640c53c7f767c6d0a7c5249029e40ea6b0903b4554f2030417b8374e400902eff2d22cf5afe24987a78eb20f51c5ae4dde93cd123204a71f49c61e59
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,93 @@
|
|
|
1
|
+
## Unreleased
|
|
2
|
+
|
|
3
|
+
## v4.1.1
|
|
4
|
+
|
|
5
|
+
Fixes missing indifferent_access import
|
|
6
|
+
|
|
7
|
+
## v4.1.0
|
|
8
|
+
|
|
9
|
+
Removes upper boundary on ActiveRecord.
|
|
10
|
+
|
|
11
|
+
Drops support for Ruby < 3.0.
|
|
12
|
+
|
|
13
|
+
Drops support for Rails < 6.0.
|
|
14
|
+
|
|
15
|
+
## v4.0.1
|
|
16
|
+
|
|
17
|
+
Fixes loading issues for apps not using the Rails engine.
|
|
18
|
+
|
|
19
|
+
## v4.0.0
|
|
20
|
+
|
|
21
|
+
Stops loading the Rails engine automatically. If you are using the engine, you need to require it explicitly by adding `require 'arturo/engine'` to `application.rb`.
|
|
22
|
+
|
|
23
|
+
Adds support for Ruby 3.3.
|
|
24
|
+
|
|
25
|
+
Returns false immediately for `feature_enabled_for?` calls with `nil` recipients.
|
|
26
|
+
|
|
27
|
+
## v3.0.0
|
|
28
|
+
|
|
29
|
+
Converts the Feature model into a mixin that should be used by services via a model generator.
|
|
30
|
+
|
|
31
|
+
Brings back the `warm_cache!` method.
|
|
32
|
+
|
|
33
|
+
Adds support for Rails 7.1.
|
|
34
|
+
|
|
35
|
+
## v2.8.0
|
|
36
|
+
|
|
37
|
+
Drop support for Ruby 2.6
|
|
38
|
+
|
|
39
|
+
Drop Support for Rails 5.0 & 5.1
|
|
40
|
+
|
|
41
|
+
Add support for Ruby 3.2
|
|
42
|
+
|
|
43
|
+
## v2.7.0
|
|
44
|
+
|
|
45
|
+
Adds ability to register cache update listeners with Arturo::FeatureCaching::AllStrategy that are called when the cache is updated
|
|
46
|
+
|
|
47
|
+
## v2.6.0
|
|
48
|
+
|
|
49
|
+
Add support for Rails 7.0
|
|
50
|
+
|
|
51
|
+
Add support for Ruby 3.0 & 3.1
|
|
52
|
+
|
|
53
|
+
Drop support for Rails 4.2
|
|
54
|
+
|
|
55
|
+
Drop support for Ruby 2.4 & 2.5
|
|
56
|
+
|
|
57
|
+
## v2.5.4
|
|
58
|
+
|
|
59
|
+
Bug fix: Explicitly require rails engine to avoid errors that ::Rails::Engine cannot be found.
|
|
60
|
+
|
|
61
|
+
## v2.5.3
|
|
62
|
+
|
|
63
|
+
Bug fix: Allow using Arturo with ActiveRecord, but without all of Rails.
|
|
64
|
+
|
|
65
|
+
## v2.5.2
|
|
66
|
+
|
|
67
|
+
Drop support for Rails 3.2.
|
|
68
|
+
|
|
69
|
+
Add support for Rails 6.1.
|
|
70
|
+
|
|
71
|
+
Switch CI from Travis to GitHub Actions.
|
|
72
|
+
|
|
73
|
+
## v2.2.0
|
|
74
|
+
|
|
75
|
+
Bug fix: making a feature-update request that fails strict params checks now returns a sensible error instead of throwing an exception
|
|
76
|
+
|
|
77
|
+
Improvement: better failed-to-update error messages
|
|
78
|
+
|
|
79
|
+
Support Matrix changes: add Rails 5.0, drop Rails 3.2, add Ruby 2.1.7, add Ruby 2.2.3, drop Ruby 1.9.3
|
|
80
|
+
|
|
81
|
+
## v2.1.0
|
|
82
|
+
|
|
83
|
+
Bug fix: `Arturo::SpecialHandling` always compares symbols as strings
|
|
84
|
+
|
|
85
|
+
Improvmement: Rails 4.2 compatibility
|
|
86
|
+
|
|
87
|
+
Improvement: relax minitest version constraints
|
|
88
|
+
|
|
89
|
+
Improvement: add `set_feature!` method to complement `enable_feature!`and `disable_feature!`
|
|
90
|
+
|
|
1
91
|
## v2.0.0
|
|
2
92
|
|
|
3
93
|
Bug fix: add missing require to initializer.
|
data/README.md
CHANGED
|
@@ -2,16 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Arturo provides feature sliders for Rails. It lets you turn features on and off
|
|
4
4
|
just like
|
|
5
|
-
[feature flippers](
|
|
5
|
+
[feature flippers](https://code.flickr.net/2009/12/02/flipping-out/),
|
|
6
6
|
but offers more fine-grained control. It supports deploying features only for
|
|
7
|
-
a given
|
|
7
|
+
a given percentage of your users and whitelisting and blacklisting users based
|
|
8
8
|
on any criteria you can express in Ruby.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
the feature's deployment percentage or change its white- or blacklist
|
|
14
|
-
settings).
|
|
10
|
+
The selection is deterministic. So if a user has a feature on Monday, the
|
|
11
|
+
user will still have it on Tuesday (unless you *decrease* the feature's
|
|
12
|
+
deployment percentage or change its white- or blacklist settings).
|
|
15
13
|
|
|
16
14
|
### A quick example
|
|
17
15
|
|
|
@@ -19,38 +17,44 @@ Trish, a developer is working on a new feature: a live feed of recent postings
|
|
|
19
17
|
in the user's city that shows up in the user's sidebar. First, she uses Arturo's
|
|
20
18
|
view helpers to control who sees the sidebar widget:
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</
|
|
29
|
-
|
|
20
|
+
```ERB
|
|
21
|
+
<%# in app/views/layout/_sidebar.html.erb: %>
|
|
22
|
+
<% if_feature_enabled(:live_postings) do %>
|
|
23
|
+
<div class='widget'>
|
|
24
|
+
<h3>Recent Postings</h3>
|
|
25
|
+
<ol id='live_postings'>
|
|
26
|
+
</ol>
|
|
27
|
+
</div>
|
|
28
|
+
<% end %>
|
|
29
|
+
```
|
|
30
30
|
|
|
31
31
|
Then Trish writes some Javascript that will poll the server for recent
|
|
32
32
|
postings and put them in the sidebar widget:
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
```js
|
|
35
|
+
// in public/javascript/live_postings.js:
|
|
36
|
+
$(function() {
|
|
37
|
+
var livePostingsList = $('#live_postings');
|
|
38
|
+
if (livePostingsList.length > 0) {
|
|
39
|
+
var updatePostingsList = function() {
|
|
40
|
+
livePostingsList.load('/listings/recent');
|
|
41
|
+
setTimeout(updatePostingsList, 30);
|
|
42
|
+
}
|
|
43
|
+
updatePostingsList();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
```
|
|
45
47
|
|
|
46
48
|
Trish uses Arturo's Controller filters to control who has access to
|
|
47
49
|
the feature:
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
```Ruby
|
|
52
|
+
# in app/controllers/postings_controller:
|
|
53
|
+
class PostingsController < ApplicationController
|
|
54
|
+
require_feature :live_postings, only: :recent
|
|
55
|
+
# ...
|
|
56
|
+
end
|
|
57
|
+
```
|
|
54
58
|
|
|
55
59
|
Trish then deploys this code to production. Nobody will see the feature yet,
|
|
56
60
|
since it's not on for anyone. (In fact, the feature doesn't yet exist
|
|
@@ -66,18 +70,9 @@ feature and deploy it to all users.
|
|
|
66
70
|
|
|
67
71
|
## Installation
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
### In Rails 3 or 4, without Bundler
|
|
74
|
-
|
|
75
|
-
$ gem install arturo --version="~> 1.0"
|
|
76
|
-
|
|
77
|
-
### In Rails 2.3
|
|
78
|
-
|
|
79
|
-
Rails 2.3 is no longer supported and has been archived on the
|
|
80
|
-
[`rails_2_3` branch](http://github.com/jamesarosen/arturo/tree/rails_2_3).
|
|
73
|
+
```Ruby
|
|
74
|
+
gem 'arturo'
|
|
75
|
+
```
|
|
81
76
|
|
|
82
77
|
## Configuration
|
|
83
78
|
|
|
@@ -85,24 +80,34 @@ Rails 2.3 is no longer supported and has been archived on the
|
|
|
85
80
|
|
|
86
81
|
#### Run the generators:
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
```
|
|
84
|
+
rails g arturo:migration
|
|
85
|
+
rails g arturo:initializer
|
|
86
|
+
rails g arturo:routes
|
|
87
|
+
rails g arturo:assets
|
|
88
|
+
rails g arturo:feature_model
|
|
89
|
+
```
|
|
92
90
|
|
|
93
91
|
#### Run the migration:
|
|
94
92
|
|
|
95
|
-
|
|
93
|
+
```
|
|
94
|
+
rake db:migrate
|
|
95
|
+
```
|
|
96
96
|
|
|
97
97
|
#### Edit the generated migration as necessary
|
|
98
98
|
|
|
99
99
|
#### Edit the configuration
|
|
100
100
|
|
|
101
|
+
#### Edit the Feature model
|
|
102
|
+
|
|
103
|
+
By default, the generated model `Arturo::Feature` inherits from `ActiveRecord::Base`. However, if you’re using multiple databases your models should inherit from an abstract class that specifies a database connection, not directly from `ActiveRecord::Base`. Update the generated model in `app/models/arturo/feature.rb` to make it use a correct database.
|
|
104
|
+
|
|
101
105
|
##### Initializer
|
|
102
106
|
|
|
103
107
|
Open up the newly-generated `config/initializers/arturo_initializer.rb`.
|
|
104
108
|
There are configuration options for the following:
|
|
105
109
|
|
|
110
|
+
* logging capabilities (see [logging](#logging))
|
|
106
111
|
* the method that determines whether a user has permission to manage features
|
|
107
112
|
(see [admin permissions](#adminpermissions))
|
|
108
113
|
* the method that returns the object that has features
|
|
@@ -113,20 +118,29 @@ There are configuration options for the following:
|
|
|
113
118
|
|
|
114
119
|
##### CSS
|
|
115
120
|
|
|
116
|
-
Open up the newly-generated `public/
|
|
121
|
+
Open up the newly-generated `public/stylesheets/arturo_customizations.css`.
|
|
117
122
|
You can add any overrides you like to the feature configuration page styles
|
|
118
|
-
here. **Do not** edit `public/
|
|
123
|
+
here. **Do not** edit `public/stylesheets/arturo.css` as that file may be
|
|
119
124
|
overwritten in future updates to Arturo.
|
|
120
125
|
|
|
121
126
|
### In other frameworks
|
|
122
127
|
|
|
123
128
|
Arturo is a Rails engine. I want to promote reuse on other frameworks by
|
|
124
129
|
extracting key pieces into mixins, though this isn't done yet. Open an
|
|
125
|
-
[issue](http://github.com/
|
|
130
|
+
[issue](http://github.com/zendesk/arturo/issues) and I'll be happy to
|
|
126
131
|
work with you on support for your favorite framework.
|
|
127
132
|
|
|
128
133
|
## Deep-Dive
|
|
129
134
|
|
|
135
|
+
### <span id='logging'>Logging</span>
|
|
136
|
+
|
|
137
|
+
You can provide a logger in order to inspect Arturo usage.
|
|
138
|
+
A potential implementation for Rails would be:
|
|
139
|
+
|
|
140
|
+
```Ruby
|
|
141
|
+
Arturo.logger = Rails.logger
|
|
142
|
+
```
|
|
143
|
+
|
|
130
144
|
### <span id='adminpermissions'>Admin Permissions</span>
|
|
131
145
|
|
|
132
146
|
`Arturo::FeatureManagement#may_manage_features?` is a method that is run in
|
|
@@ -134,15 +148,19 @@ the context of a Controller or View instance. It should return `true` if
|
|
|
134
148
|
and only if the current user may manage permissions. The default implementation
|
|
135
149
|
is as follows:
|
|
136
150
|
|
|
137
|
-
|
|
151
|
+
```Ruby
|
|
152
|
+
current_user.present? && current_user.admin?
|
|
153
|
+
```
|
|
138
154
|
|
|
139
155
|
You can change the implementation in
|
|
140
156
|
`config/initializers/arturo_initializer.rb`. A reasonable implementation
|
|
141
157
|
might be
|
|
142
158
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
159
|
+
```Ruby
|
|
160
|
+
Arturo.permit_management do
|
|
161
|
+
signed_in? && current_user.can?(:manage_features)
|
|
162
|
+
end
|
|
163
|
+
```
|
|
146
164
|
|
|
147
165
|
### <span id='featurerecipients'>Feature Recipients</span>
|
|
148
166
|
|
|
@@ -163,15 +181,19 @@ The default implementation simply returns `current_user`. Like
|
|
|
163
181
|
in `config/initializers/arturo_initializer.rb`. If you want to deploy features
|
|
164
182
|
on a per-account basis, a reasonable implementation might be
|
|
165
183
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
184
|
+
```Ruby
|
|
185
|
+
Arturo.feature_recipient do
|
|
186
|
+
current_account
|
|
187
|
+
end
|
|
188
|
+
```
|
|
169
189
|
|
|
170
190
|
or
|
|
171
191
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
192
|
+
```Ruby
|
|
193
|
+
Arturo.feature_recipient do
|
|
194
|
+
current_user.account
|
|
195
|
+
end
|
|
196
|
+
```
|
|
175
197
|
|
|
176
198
|
If the block returns `nil`, the feature will be disabled.
|
|
177
199
|
|
|
@@ -182,24 +204,30 @@ will have a feature. For example, if all premium users should have the
|
|
|
182
204
|
`:awesome` feature, place the following in
|
|
183
205
|
`config/initializers/arturo_initializer.rb`:
|
|
184
206
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
207
|
+
```Ruby
|
|
208
|
+
Arturo::Feature.whitelist(:awesome) do |user|
|
|
209
|
+
user.account.premium?
|
|
210
|
+
end
|
|
211
|
+
```
|
|
188
212
|
|
|
189
213
|
If, on the other hand, no users on the free plan should have the
|
|
190
214
|
`:awesome` feature, place the following in
|
|
191
215
|
`config/initializers/arturo_initializer.rb`:
|
|
192
216
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
217
|
+
```Ruby
|
|
218
|
+
Arturo::Feature.blacklist(:awesome) do |user|
|
|
219
|
+
user.account.free?
|
|
220
|
+
end
|
|
221
|
+
```
|
|
196
222
|
|
|
197
223
|
If you want to whitelist or blacklist large groups of features at once, you
|
|
198
224
|
can move the feature argument into the block:
|
|
199
225
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
226
|
+
```Ruby
|
|
227
|
+
Arturo::Feature.whitelist do |feature, user|
|
|
228
|
+
user.account.has?(feature.to_sym)
|
|
229
|
+
end
|
|
230
|
+
```
|
|
203
231
|
|
|
204
232
|
### Feature Conditionals
|
|
205
233
|
|
|
@@ -214,12 +242,14 @@ use a before filter. The following will raise a 403 Forbidden error for
|
|
|
214
242
|
every action within `BookHoldsController` that is invoked by a user who
|
|
215
243
|
does not have the `:hold_book` feature.
|
|
216
244
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
245
|
+
```Ruby
|
|
246
|
+
class BookHoldsController < ApplicationController
|
|
247
|
+
require_feature :hold_book
|
|
248
|
+
end
|
|
249
|
+
```
|
|
220
250
|
|
|
221
251
|
`require_feature` accepts as a second argument a `Hash` that it passes on
|
|
222
|
-
to `
|
|
252
|
+
to `before_action`, so you can use `:only` and `:except` to specify exactly
|
|
223
253
|
which actions are filtered.
|
|
224
254
|
|
|
225
255
|
If you want to customize the page that is rendered on 403 Forbidden
|
|
@@ -229,26 +259,32 @@ check there before falling back on Arturo's forbidden page.
|
|
|
229
259
|
|
|
230
260
|
#### Conditional Evaluation
|
|
231
261
|
|
|
232
|
-
Both controllers and views have access to the `if_feature_enabled
|
|
262
|
+
Both controllers and views have access to the `if_feature_enabled?` and
|
|
233
263
|
`feature_enabled?` methods. The former is used like so:
|
|
234
264
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
265
|
+
```ERB
|
|
266
|
+
<% if_feature_enabled?(:reserve_table) %>
|
|
267
|
+
<%= link_to 'Reserve a table', new_restaurant_reservation_path(:restaurant_id => @restaurant) %>
|
|
268
|
+
<% end %>
|
|
269
|
+
```
|
|
238
270
|
|
|
239
271
|
The latter can be used like so:
|
|
240
272
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
273
|
+
```Ruby
|
|
274
|
+
def widgets_for_sidebar
|
|
275
|
+
widgets = []
|
|
276
|
+
widgets << twitter_widget if feature_enabled?(:twitter_integration)
|
|
277
|
+
...
|
|
278
|
+
widgets
|
|
279
|
+
end
|
|
280
|
+
```
|
|
247
281
|
|
|
248
282
|
#### Rack Middleware
|
|
249
283
|
|
|
250
|
-
|
|
251
|
-
|
|
284
|
+
```Ruby
|
|
285
|
+
require 'arturo'
|
|
286
|
+
use Arturo::Middleware, feature: :my_feature
|
|
287
|
+
```
|
|
252
288
|
|
|
253
289
|
#### Outside a Controller
|
|
254
290
|
|
|
@@ -256,11 +292,15 @@ If you want to check availability outside of a controller or view (really
|
|
|
256
292
|
outside of something that has `Arturo::FeatureAvailability` mixed in), you
|
|
257
293
|
can ask either
|
|
258
294
|
|
|
259
|
-
|
|
295
|
+
```Ruby
|
|
296
|
+
Arturo.feature_enabled_for?(:foo, recipient)
|
|
297
|
+
```
|
|
260
298
|
|
|
261
299
|
or the slightly fancier
|
|
262
300
|
|
|
263
|
-
|
|
301
|
+
```Ruby
|
|
302
|
+
Arturo.foo_enabled_for?(recipient)
|
|
303
|
+
```
|
|
264
304
|
|
|
265
305
|
Both check whether the `foo` feature exists and is enabled for `recipient`.
|
|
266
306
|
|
|
@@ -276,15 +316,24 @@ To enable caching `Feature` lookups, mix `Arturo::FeatureCaching` into
|
|
|
276
316
|
`Arturo::Feature` and set the `cache_ttl`. This is best done in an
|
|
277
317
|
initializer:
|
|
278
318
|
|
|
279
|
-
|
|
280
|
-
|
|
319
|
+
```Ruby
|
|
320
|
+
Arturo::Feature.extend(Arturo::FeatureCaching)
|
|
321
|
+
Arturo::Feature.cache_ttl = 10.minutes
|
|
322
|
+
```
|
|
281
323
|
|
|
282
324
|
You can also warm the cache on startup:
|
|
283
325
|
|
|
284
|
-
|
|
326
|
+
```Ruby
|
|
327
|
+
Arturo::Feature.warm_cache!
|
|
328
|
+
```
|
|
285
329
|
|
|
286
330
|
This will pre-fetch all `Feature`s and put them in the cache.
|
|
287
331
|
|
|
332
|
+
To use the current cache state when you can't fetch updates from origin:
|
|
333
|
+
|
|
334
|
+
```Ruby
|
|
335
|
+
Arturo::Feature.extend_cache_on_failure = true
|
|
336
|
+
```
|
|
288
337
|
|
|
289
338
|
The following is the **intended** support for integration with view caching:
|
|
290
339
|
|
|
@@ -302,6 +351,6 @@ on [Sliders](http://en.wikipedia.org/wiki/Sliders).
|
|
|
302
351
|
|
|
303
352
|
## Quality Metrics
|
|
304
353
|
|
|
305
|
-
[](https://github.com/zendesk/arturo/actions?query=workflow%3ACI)
|
|
306
355
|
|
|
307
|
-
[](https://codeclimate.com/github/zendesk/arturo)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'action_controller'
|
|
2
3
|
require 'arturo/feature_params_support'
|
|
3
4
|
|
|
@@ -13,17 +14,10 @@ module Arturo
|
|
|
13
14
|
include Arturo::FeatureManagement
|
|
14
15
|
include Arturo::FeatureParamsSupport
|
|
15
16
|
|
|
16
|
-
unloadable
|
|
17
17
|
respond_to :html, :json, :xml
|
|
18
|
-
before_filter :require_permission
|
|
19
|
-
before_filter :load_feature, :only => [ :show, :edit, :update, :destroy ]
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
self
|
|
24
|
-
end
|
|
25
|
-
helper_method :arturo_engine
|
|
26
|
-
end
|
|
19
|
+
before_action :require_permission
|
|
20
|
+
before_action :load_feature, :only => [ :show, :edit, :update, :destroy ]
|
|
27
21
|
|
|
28
22
|
def index
|
|
29
23
|
@features = Arturo::Feature.all
|
|
@@ -37,7 +31,7 @@ module Arturo
|
|
|
37
31
|
feature = Arturo::Feature.find_by_id(id)
|
|
38
32
|
if feature.blank?
|
|
39
33
|
errors << t('arturo.features.flash.no_such_feature', :id => id)
|
|
40
|
-
elsif feature.
|
|
34
|
+
elsif feature.update(attributes)
|
|
41
35
|
updated_count += 1
|
|
42
36
|
else
|
|
43
37
|
errors << t('arturo.features.flash.error_updating', :id => id, :errors => feature.errors.full_messages.to_sentence)
|
|
@@ -76,11 +70,11 @@ module Arturo
|
|
|
76
70
|
end
|
|
77
71
|
|
|
78
72
|
def update
|
|
79
|
-
if @feature.
|
|
73
|
+
if @feature.update(feature_params)
|
|
80
74
|
flash[:notice] = t('arturo.features.flash.updated', :name => @feature.to_s)
|
|
81
75
|
redirect_to arturo_engine.feature_path(@feature)
|
|
82
76
|
else
|
|
83
|
-
flash[:alert] = t('arturo.features.flash.error_updating', :name => @feature.
|
|
77
|
+
flash[:alert] = t('arturo.features.flash.error_updating', :name => @feature.name, :errors => @feature.errors.full_messages.join("\n"))
|
|
84
78
|
render :action => 'edit'
|
|
85
79
|
end
|
|
86
80
|
end
|
|
@@ -110,4 +104,3 @@ module Arturo
|
|
|
110
104
|
end
|
|
111
105
|
|
|
112
106
|
end
|
|
113
|
-
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<%# frozen_string_literal: true %>
|
|
1
2
|
<tr class='feature' id="feature_<%= feature.id %>">
|
|
2
3
|
<td><code class='ruby symbol'><%= feature.symbol %></code></td>
|
|
3
4
|
<td><%= deployment_percentage_range_and_output_tags("features[#{feature.id}][deployment_percentage]", feature.deployment_percentage) %></td>
|
data/config/locales/en.yml
CHANGED
|
@@ -35,7 +35,7 @@ en:
|
|
|
35
35
|
created: "Created %{name}"
|
|
36
36
|
error_creating: "Sorry, there was an error creating the feature."
|
|
37
37
|
updated: "Updated %{name}"
|
|
38
|
-
error_updating: "Could not update
|
|
38
|
+
error_updating: "Could not update %{name}: %{errors}."
|
|
39
39
|
removed: "Removed %{name}"
|
|
40
40
|
error_removing: "Sorry, there was an error removing %{name}"
|
|
41
41
|
no_such_feature:
|
data/config/routes.rb
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
put 'features', :to => 'arturo/features#update_all', :as => 'features'
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
else
|
|
9
|
-
Arturo::Engine.routes.draw do
|
|
10
|
-
resources :features, :controller => 'arturo/features'
|
|
11
|
-
put 'features', :to => 'arturo/features#update_all', :as => 'features_update_all'
|
|
12
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
Arturo::Engine.routes.draw do
|
|
3
|
+
resources :features, :controller => 'arturo/features'
|
|
4
|
+
put 'features', :to => 'arturo/features#update_all', :as => 'features_update_all'
|
|
13
5
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Arturo
|
|
2
3
|
|
|
3
4
|
# Adds before filters to controllers for specifying that actions
|
|
@@ -13,13 +14,13 @@ module Arturo
|
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def on_feature_disabled(feature_name)
|
|
16
|
-
render :
|
|
17
|
+
render :plain => 'Forbidden', :status => 403
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
module ClassMethods
|
|
20
21
|
|
|
21
22
|
def require_feature(name, options = {})
|
|
22
|
-
|
|
23
|
+
send(:before_action, options) do |controller|
|
|
23
24
|
unless controller.feature_enabled?(name)
|
|
24
25
|
controller.on_feature_disabled(name)
|
|
25
26
|
end
|
data/lib/arturo/engine.rb
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
require 'arturo/middleware'
|
|
3
|
+
require 'rails/engine'
|
|
3
4
|
|
|
4
5
|
module Arturo
|
|
5
6
|
class Engine < ::Rails::Engine
|
|
6
|
-
ActiveSupport.on_load(:action_controller) do
|
|
7
|
-
include Arturo::FeatureAvailability
|
|
8
|
-
helper Arturo::FeatureAvailability
|
|
9
|
-
include Arturo::ControllerFilters
|
|
10
|
-
helper Arturo::FeatureManagement
|
|
11
|
-
end
|
|
12
|
-
|
|
13
7
|
root = File.expand_path("../../..", __FILE__)
|
|
14
8
|
config.autoload_paths = ["#{root}/app/helpers", "#{root}/app/controllers"]
|
|
15
9
|
config.eager_load_paths = []
|