featury 1.0.0.rc22 → 1.0.0.rc24
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/README.md +43 -13
- data/lib/featury/actions/service/factory.rb +21 -6
- data/lib/featury/callbacks/workspace.rb +2 -2
- data/lib/featury/features/collection.rb +3 -3
- data/lib/featury/features/dsl.rb +11 -1
- data/lib/featury/features/feature.rb +5 -6
- data/lib/featury/groups/collection.rb +1 -1
- data/lib/featury/groups/dsl.rb +11 -1
- data/lib/featury/groups/group.rb +5 -3
- data/lib/featury/info/dsl.rb +5 -9
- data/lib/featury/info/result.rb +68 -0
- data/lib/featury/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c1b72f8275c2ade5b4e3716b598937fa8c4f243dfa142c17c9cc675523b9f70
|
4
|
+
data.tar.gz: 6112766f0f732d53a04b807e6f5af30f5125077a41a5ca043f43c0145bbba708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d3f21be19cfb9090f9c79ac9ce52d060eaea14ea014384ed2a3f1911f962058d58e87e796c36a28575b24841bf610dd0c2565d16f7a3c0a73a7343f6273b866
|
7
|
+
data.tar.gz: 38df69d5f0c94cef5213279b39966c79c006dc1ddff5ccb54f715e51b07c4e42bd2d84858659e3273fe3ddf48efcbd08d244afa40908b5fbefb8a0d1bfb3cd58
|
data/README.md
CHANGED
@@ -56,7 +56,7 @@ class ApplicationFeature < Featury::Base
|
|
56
56
|
features.all? { |feature| Flipper.disable(feature, *options.values) }
|
57
57
|
end
|
58
58
|
|
59
|
-
action :add do |features:, **options|
|
59
|
+
action :add, web: :regular do |features:, **options|
|
60
60
|
features.all? { |feature| Flipper.add(feature, *options.values) }
|
61
61
|
end
|
62
62
|
|
@@ -90,10 +90,10 @@ class User::OnboardingFeature < ApplicationFeature
|
|
90
90
|
|
91
91
|
condition ->(resources:) { resources.user.onboarding_awaiting? }
|
92
92
|
|
93
|
-
|
93
|
+
feature :passage, description: "User onboarding passage feature" # => :user_onboarding_passage
|
94
94
|
|
95
|
-
|
96
|
-
|
95
|
+
group BillingFeature, description: "Billing functionality group"
|
96
|
+
group PaymentSystemFeature, description: "Payment system functionality group"
|
97
97
|
end
|
98
98
|
```
|
99
99
|
|
@@ -101,8 +101,8 @@ end
|
|
101
101
|
class BillingFeature < ApplicationFeature
|
102
102
|
prefix :billing
|
103
103
|
|
104
|
-
|
105
|
-
|
104
|
+
feature :api, description: "Billing API feature" # => :billing_api
|
105
|
+
feature :webhooks, description: "Billing webhooks feature" # => :billing_webhooks
|
106
106
|
end
|
107
107
|
```
|
108
108
|
|
@@ -110,8 +110,8 @@ end
|
|
110
110
|
class PaymentSystemFeature < ApplicationFeature
|
111
111
|
prefix :payment_system
|
112
112
|
|
113
|
-
|
114
|
-
|
113
|
+
feature :api, description: "Payment system API feature" # => :payment_system_api
|
114
|
+
feature :webhooks, description: "Payment system webhooks feature" # => :payment_system_webhooks
|
115
115
|
end
|
116
116
|
```
|
117
117
|
|
@@ -161,6 +161,20 @@ In the preceding example, there might be a scenario where the payment system is
|
|
161
161
|
undergoing technical maintenance and therefore is temporarily shut down.
|
162
162
|
Consequently, the onboarding process for new users will be halted until further notice.
|
163
163
|
|
164
|
+
#### Feature and Group descriptions
|
165
|
+
|
166
|
+
When defining features and groups, you can provide descriptions to add more context about what they do:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
# Adding a feature with description
|
170
|
+
feature :api, description: "External API integration"
|
171
|
+
|
172
|
+
# Adding a group with description
|
173
|
+
group PaymentSystemFeature, description: "Payment processing functionality"
|
174
|
+
```
|
175
|
+
|
176
|
+
These descriptions are preserved in the feature tree and can be accessed via the info method.
|
177
|
+
|
164
178
|
#### Information about features
|
165
179
|
|
166
180
|
```ruby
|
@@ -168,11 +182,27 @@ info = User::OnboardingFeature.info
|
|
168
182
|
```
|
169
183
|
|
170
184
|
```ruby
|
171
|
-
|
172
|
-
info.
|
173
|
-
info.
|
174
|
-
|
175
|
-
|
185
|
+
# Feature actions information (all actions and web actions)
|
186
|
+
info.actions.all # All actions: [:enabled?, :disabled?, :enable, :disable, :add]
|
187
|
+
info.actions.web.all # Web actions: [:enabled?, :disabled?, :enable, :disable, :add]
|
188
|
+
|
189
|
+
# Access specific web actions by their web: option name
|
190
|
+
info.actions.web.enabled # Returns the method name (:enabled?) that was defined with `web: :enabled?`
|
191
|
+
info.actions.web.enable # Returns the method name (:enable) that was defined with `web: :enable`
|
192
|
+
info.actions.web.disable # Returns the method name (:disable) that was defined with `web: :disable`
|
193
|
+
|
194
|
+
# Feature resources information
|
195
|
+
info.resources # Feature resources of the current class.
|
196
|
+
|
197
|
+
# Feature flags information (with descriptions)
|
198
|
+
info.features # Feature flags of the current class with their names and descriptions.
|
199
|
+
|
200
|
+
# Feature groups information (with descriptions)
|
201
|
+
info.groups # Feature groups of the current class with their class references and descriptions.
|
202
|
+
|
203
|
+
# Complete feature tree (features and nested groups)
|
204
|
+
info.tree.features # Direct features of the current class.
|
205
|
+
info.tree.groups # Features from nested groups.
|
176
206
|
```
|
177
207
|
|
178
208
|
## Contributing
|
@@ -31,10 +31,25 @@ module Featury
|
|
31
31
|
|
32
32
|
input :action, type: Featury::Actions::Action
|
33
33
|
|
34
|
-
input :collection_of_resources,
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
input :collection_of_resources,
|
35
|
+
type: Featury::Resources::Collection,
|
36
|
+
required: false,
|
37
|
+
default: Featury::Resources::Collection.new
|
38
|
+
|
39
|
+
input :collection_of_conditions,
|
40
|
+
type: Featury::Conditions::Collection,
|
41
|
+
required: false,
|
42
|
+
default: Featury::Conditions::Collection.new
|
43
|
+
|
44
|
+
input :collection_of_features,
|
45
|
+
type: Featury::Features::Collection,
|
46
|
+
required: false,
|
47
|
+
default: Featury::Features::Collection.new
|
48
|
+
|
49
|
+
input :collection_of_groups,
|
50
|
+
type: Featury::Groups::Collection,
|
51
|
+
required: false,
|
52
|
+
default: Featury::Groups::Collection.new
|
38
53
|
|
39
54
|
output :all_true, type: [TrueClass, FalseClass]
|
40
55
|
|
@@ -65,7 +80,7 @@ module Featury
|
|
65
80
|
[resource.name, inputs.public_send(resource.name)]
|
66
81
|
end
|
67
82
|
|
68
|
-
inputs.action.block.call(features: inputs.collection_of_features.
|
83
|
+
inputs.action.block.call(features: inputs.collection_of_features.names, **options)
|
69
84
|
end
|
70
85
|
|
71
86
|
def groups_are_true
|
@@ -74,7 +89,7 @@ module Featury
|
|
74
89
|
end
|
75
90
|
|
76
91
|
inputs.collection_of_groups.all? do |group|
|
77
|
-
group.
|
92
|
+
group.group_class.public_send(inputs.action.name, **arguments)
|
78
93
|
end
|
79
94
|
end
|
80
95
|
end
|
@@ -9,7 +9,7 @@ module Featury
|
|
9
9
|
Featury::Callbacks::Service.call!(
|
10
10
|
action: action.name,
|
11
11
|
callbacks: collection_of_callbacks.before,
|
12
|
-
features: collection_of_features.
|
12
|
+
features: collection_of_features.names
|
13
13
|
)
|
14
14
|
|
15
15
|
result = super
|
@@ -17,7 +17,7 @@ module Featury
|
|
17
17
|
Featury::Callbacks::Service.call!(
|
18
18
|
action: action.name,
|
19
19
|
callbacks: collection_of_callbacks.after,
|
20
|
-
features: collection_of_features.
|
20
|
+
features: collection_of_features.names
|
21
21
|
)
|
22
22
|
|
23
23
|
result
|
@@ -4,14 +4,14 @@ module Featury
|
|
4
4
|
module Features
|
5
5
|
class Collection
|
6
6
|
extend Forwardable
|
7
|
-
def_delegators :@collection, :<<, :each, :map, :merge
|
7
|
+
def_delegators :@collection, :<<, :each, :map, :merge, :to_a, :empty?
|
8
8
|
|
9
9
|
def initialize(collection = Set.new)
|
10
10
|
@collection = collection
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
map(&:
|
13
|
+
def names
|
14
|
+
map(&:name)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/featury/features/dsl.rb
CHANGED
@@ -20,12 +20,22 @@ module Featury
|
|
20
20
|
self.feature_prefix = prefix
|
21
21
|
end
|
22
22
|
|
23
|
+
# DEPRECATED: Need to use the `feature` method instead of `features`.
|
23
24
|
def features(*names)
|
25
|
+
Kernel.warn "DEPRECATION WARNING: " \
|
26
|
+
"Method `features` is deprecated; " \
|
27
|
+
"use `feature` instead. " \
|
28
|
+
"It will be removed in one of the next releases."
|
29
|
+
|
24
30
|
names.each do |name|
|
25
|
-
collection_of_features << Feature.new(feature_prefix, name)
|
31
|
+
collection_of_features << Feature.new(prefix: feature_prefix, name:, description: nil)
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
35
|
+
def feature(name, description: nil)
|
36
|
+
collection_of_features << Feature.new(prefix: feature_prefix, name:, description:)
|
37
|
+
end
|
38
|
+
|
29
39
|
def feature_prefix=(value)
|
30
40
|
@feature_prefix = value
|
31
41
|
end
|
@@ -3,13 +3,12 @@
|
|
3
3
|
module Featury
|
4
4
|
module Features
|
5
5
|
class Feature
|
6
|
-
|
7
|
-
|
8
|
-
@name = name
|
9
|
-
end
|
6
|
+
attr_reader :name,
|
7
|
+
:description
|
10
8
|
|
11
|
-
def
|
12
|
-
:"#{
|
9
|
+
def initialize(prefix:, name:, description:)
|
10
|
+
@name = :"#{prefix}_#{name}"
|
11
|
+
@description = description
|
13
12
|
end
|
14
13
|
end
|
15
14
|
end
|
@@ -4,7 +4,7 @@ module Featury
|
|
4
4
|
module Groups
|
5
5
|
class Collection
|
6
6
|
extend Forwardable
|
7
|
-
def_delegators :@collection, :<<, :each, :map, :filter, :to_h, :merge, :all?
|
7
|
+
def_delegators :@collection, :<<, :each, :map, :flat_map, :filter, :to_h, :merge, :to_a, :all?, :empty?
|
8
8
|
|
9
9
|
def initialize(collection = Set.new)
|
10
10
|
@collection = collection
|
data/lib/featury/groups/dsl.rb
CHANGED
@@ -16,12 +16,22 @@ module Featury
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
+
# DEPRECATED: Need to use the `group` method instead of `groups`.
|
19
20
|
def groups(*groups)
|
21
|
+
Kernel.warn "DEPRECATION WARNING: " \
|
22
|
+
"Method `groups` is deprecated; " \
|
23
|
+
"use `group` instead. " \
|
24
|
+
"It will be removed in one of the next releases."
|
25
|
+
|
20
26
|
groups.each do |group|
|
21
|
-
collection_of_groups << Group.new(group)
|
27
|
+
collection_of_groups << Group.new(group:, description: nil)
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
31
|
+
def group(group, description: nil)
|
32
|
+
collection_of_groups << Group.new(group:, description:)
|
33
|
+
end
|
34
|
+
|
25
35
|
def collection_of_groups
|
26
36
|
@collection_of_groups ||= Collection.new
|
27
37
|
end
|
data/lib/featury/groups/group.rb
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
module Featury
|
4
4
|
module Groups
|
5
5
|
class Group
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :group_class,
|
7
|
+
:description
|
7
8
|
|
8
|
-
def initialize(group)
|
9
|
-
@
|
9
|
+
def initialize(group:, description:)
|
10
|
+
@group_class = group
|
11
|
+
@description = description
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
data/lib/featury/info/dsl.rb
CHANGED
@@ -8,17 +8,13 @@ module Featury
|
|
8
8
|
end
|
9
9
|
|
10
10
|
module ClassMethods
|
11
|
-
def info
|
11
|
+
def info
|
12
12
|
Featury::Info::Result.new(
|
13
13
|
actions: Featury::Info::Result::Actions.new(collection_of_actions),
|
14
|
-
resources: collection_of_resources.names,
|
15
|
-
features: collection_of_features.
|
16
|
-
groups:
|
17
|
-
tree: collection_of_features.
|
18
|
-
collection_of_groups.map do |group|
|
19
|
-
group.group.info.tree
|
20
|
-
end
|
21
|
-
)
|
14
|
+
resources: Featury::Info::Result::Resources.new(collection_of_resources).all.names,
|
15
|
+
features: Featury::Info::Result::Features.new(collection_of_features).all,
|
16
|
+
groups: Featury::Info::Result::Groups.new(collection_of_groups).all,
|
17
|
+
tree: Featury::Info::Result::Tree.new(collection_of_features, collection_of_groups).all
|
22
18
|
)
|
23
19
|
end
|
24
20
|
|
data/lib/featury/info/result.rb
CHANGED
@@ -27,6 +27,74 @@ module Featury
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
class Resources
|
31
|
+
attr_reader :all
|
32
|
+
|
33
|
+
def initialize(collection_of_resources)
|
34
|
+
@all = collection_of_resources
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Features
|
39
|
+
attr_reader :all
|
40
|
+
|
41
|
+
def initialize(collection_of_features)
|
42
|
+
@all = collection_of_features
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Groups
|
47
|
+
attr_reader :all
|
48
|
+
|
49
|
+
def initialize(collection_of_groups)
|
50
|
+
@all = collection_of_groups
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Tree
|
55
|
+
attr_reader :all
|
56
|
+
|
57
|
+
class Features
|
58
|
+
attr_reader :features,
|
59
|
+
:groups
|
60
|
+
|
61
|
+
def initialize(features, groups)
|
62
|
+
@features = features.map do |feature|
|
63
|
+
Feature.new(
|
64
|
+
name: feature.name,
|
65
|
+
description: feature.description
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
@groups = groups.flat_map do |group|
|
70
|
+
group.group_class.info.tree
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Feature
|
75
|
+
attr_reader :name,
|
76
|
+
:description
|
77
|
+
|
78
|
+
def initialize(name:, description:)
|
79
|
+
@name = name
|
80
|
+
@description = description
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def initialize(features, groups)
|
86
|
+
@all = Features.new(features, groups)
|
87
|
+
|
88
|
+
# @groups = groups.flat_map do |group|
|
89
|
+
# group.group_class.info.tree
|
90
|
+
# end
|
91
|
+
end
|
92
|
+
|
93
|
+
# nested: @groups.flat_map do |group|
|
94
|
+
# group.group_class.info.tree
|
95
|
+
# end
|
96
|
+
end
|
97
|
+
|
30
98
|
attr_reader :actions,
|
31
99
|
:resources,
|
32
100
|
:features,
|
data/lib/featury/version.rb
CHANGED