featury 1.0.0.rc12 → 1.0.0.rc14

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: da71740ad8da839e25609eca445d6571c6addf96cbf3237f0d274f866ef7c04d
4
- data.tar.gz: 0dcf024bda1d4573fa0a0231ac03393490c18559c923786e8787069ff994eb1a
3
+ metadata.gz: e96956d416b000864c67950857203f8b5684e6340b5f73bce937415ec19b4847
4
+ data.tar.gz: b55c10a5650293385194cccf8b18bf954bccecac287b244b80801a6d5ec7b587
5
5
  SHA512:
6
- metadata.gz: 2a7a0ba73969fa85cc350fabd84a3feeb7e54c984100e8eb4659a572659d9e20ecd132f3a8446a0aecac477bcc807afc28c0ee82b9bff78da4b02f3eb5a3913e
7
- data.tar.gz: 1b4dee48909191577fbd353ad1f75932c0b0dbe96e21ec73c5a60813af8b57d7e3fbff48fa82118ded6c8d3f2b94623d4955320eb371a6d03c8a0066ca0993d7
6
+ metadata.gz: 4c3e6a1e487b2987c0d8ac8f9177be1fe63191b6f2522b9d355db792c03cf40ba378b5b9d0c58ac90c439e1c587ca3e384da99287dd1f292b7dbebf2250b1bf4
7
+ data.tar.gz: '0193892e10d804f0edde8bbc201eb8c8c42de5209d54d23f2f990da1a571aa83e9efcbbf0a99c7a4bdd052d25cb3968d394e368d52d1b713340cbaf62be7bcd2'
data/README.md CHANGED
@@ -26,7 +26,7 @@ gem "featury"
26
26
  #### Basic class for your features
27
27
 
28
28
  For instance, assume that you are utilizing Flipper for managing features.
29
- In such scenario, the base class could potentially be structured as follows:
29
+ In such a scenario, the base class could potentially be structured as follows:
30
30
 
31
31
  ```ruby
32
32
  class ApplicationFeature < Featury::Base
@@ -45,19 +45,27 @@ class ApplicationFeature < Featury::Base
45
45
  action :disable do |features:, **options|
46
46
  features.all? { |feature| Flipper.disable(feature, *options.values) }
47
47
  end
48
+
49
+ before do |action:, features:|
50
+ Slack::API::Notify.call!(action:, features:)
51
+ end
52
+
53
+ after do |action:, features:|
54
+ Slack::API::Notify.call!(action:, features:)
55
+ end
48
56
  end
49
57
  ```
50
58
 
51
59
  #### Features of your project
52
60
 
53
61
  ```ruby
54
- class UserFeature::Onboarding < ApplicationFeature
62
+ class User::OnboardingFeature < ApplicationFeature
63
+ prefix :user_onboarding
64
+
55
65
  resource :user, type: User
56
66
 
57
67
  condition ->(resources:) { resources.user.onboarding_awaiting? }
58
68
 
59
- prefix :user_onboarding
60
-
61
69
  features :passage # => :user_onboarding_passage
62
70
 
63
71
  groups BillingFeature,
@@ -104,16 +112,16 @@ Each of these actions will be applied to every feature flag.
104
112
  Subsequently, the outcome of these actions will be contingent upon the combined results of all feature flags.
105
113
 
106
114
  ```ruby
107
- UserFeature::Onboarding.enabled?(user:) # => true
108
- UserFeature::Onboarding.disabled?(user:) # => false
109
- UserFeature::Onboarding.enable(user:) # => true
110
- UserFeature::Onboarding.disable(user:) # => true
115
+ User::OnboardingFeature.enabled?(user:) # => true
116
+ User::OnboardingFeature.disabled?(user:) # => false
117
+ User::OnboardingFeature.enable(user:) # => true
118
+ User::OnboardingFeature.disable(user:) # => true
111
119
  ```
112
120
 
113
121
  You can also utilize the `with` method to pass necessary arguments.
114
122
 
115
123
  ```ruby
116
- feature = UserFeature::Onboarding.with(user:)
124
+ feature = User::OnboardingFeature.with(user:)
117
125
 
118
126
  feature.enabled? # => true
119
127
  feature.disabled? # => false
data/lib/featury/base.rb CHANGED
@@ -4,6 +4,7 @@ module Featury
4
4
  class Base
5
5
  include Context::DSL
6
6
  include Actions::DSL
7
+ include Callbacks::DSL
7
8
  include Groups::DSL
8
9
  include Features::DSL
9
10
  include Conditions::DSL
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Featury
4
+ module Callbacks
5
+ class Callback
6
+ attr_reader :desired_actions, :block
7
+
8
+ def initialize(stage:, desired_actions:, block:)
9
+ @stage = stage.to_sym
10
+ @desired_actions = desired_actions
11
+ @block = block
12
+ end
13
+
14
+ def before?
15
+ @stage == :before
16
+ end
17
+
18
+ def after?
19
+ @stage == :after
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Featury
4
+ module Callbacks
5
+ class Collection
6
+ extend Forwardable
7
+ def_delegators :@collection, :<<, :filter, :each, :map, :merge, :find
8
+
9
+ def initialize(collection = Set.new)
10
+ @collection = collection
11
+ end
12
+
13
+ def desired_actions(include:)
14
+ Collection.new(
15
+ filter do |callback|
16
+ callback.desired_actions.blank? ||
17
+ callback.desired_actions.include?(include)
18
+ end
19
+ )
20
+ end
21
+
22
+ def before
23
+ Collection.new(filter(&:before?))
24
+ end
25
+
26
+ def after
27
+ Collection.new(filter(&:after?))
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Featury
4
+ module Callbacks
5
+ module DSL
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ base.include(Workspace)
9
+ end
10
+
11
+ module ClassMethods
12
+ def inherited(child)
13
+ super
14
+
15
+ child.send(:collection_of_callbacks).merge(collection_of_callbacks)
16
+ end
17
+
18
+ private
19
+
20
+ def before(*actions)
21
+ collection_of_callbacks << Callback.new(
22
+ stage: :before,
23
+ desired_actions: actions,
24
+ block: ->(**arguments) { yield(**arguments) }
25
+ )
26
+ end
27
+
28
+ def after(*actions)
29
+ collection_of_callbacks << Callback.new(
30
+ stage: :after,
31
+ desired_actions: actions,
32
+ block: ->(**arguments) { yield(**arguments) }
33
+ )
34
+ end
35
+
36
+ def collection_of_callbacks
37
+ @collection_of_callbacks ||= Collection.new
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Featury
4
+ module Callbacks
5
+ class Service
6
+ def self.call!(...)
7
+ new(...).call!
8
+ end
9
+
10
+ def initialize(action:, callbacks:, features:)
11
+ @action = action
12
+ @callbacks = callbacks
13
+ @features = features
14
+ end
15
+
16
+ def call!
17
+ @callbacks.desired_actions(include: @action).each do |callback|
18
+ callback.block.call(action: @action, features: @features)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Featury
4
+ module Callbacks
5
+ module Workspace
6
+ private
7
+
8
+ def call!(action:, collection_of_callbacks:, collection_of_features:, **) # rubocop:disable Metrics/MethodLength
9
+ Featury::Callbacks::Service.call!(
10
+ action: action.name,
11
+ callbacks: collection_of_callbacks.before,
12
+ features: collection_of_features.list
13
+ )
14
+
15
+ result = super
16
+
17
+ Featury::Callbacks::Service.call!(
18
+ action: action.name,
19
+ callbacks: collection_of_callbacks.after,
20
+ features: collection_of_features.list
21
+ )
22
+
23
+ result
24
+ end
25
+ end
26
+ end
27
+ end
@@ -32,6 +32,7 @@ module Featury
32
32
  :_call!,
33
33
  action:,
34
34
  incoming_arguments: arguments.symbolize_keys,
35
+ collection_of_callbacks:,
35
36
  collection_of_resources:,
36
37
  collection_of_conditions:,
37
38
  collection_of_features:,
@@ -7,6 +7,7 @@ module Featury
7
7
 
8
8
  attr_reader :action,
9
9
  :incoming_arguments,
10
+ :collection_of_callbacks,
10
11
  :collection_of_conditions,
11
12
  :collection_of_features,
12
13
  :collection_of_groups
@@ -14,6 +15,7 @@ module Featury
14
15
  def _call!(
15
16
  action:,
16
17
  incoming_arguments:,
18
+ collection_of_callbacks:,
17
19
  collection_of_resources:,
18
20
  collection_of_conditions:,
19
21
  collection_of_features:,
@@ -22,6 +24,7 @@ module Featury
22
24
  call!(
23
25
  action:,
24
26
  incoming_arguments:,
27
+ collection_of_callbacks:,
25
28
  collection_of_resources:,
26
29
  collection_of_conditions:,
27
30
  collection_of_features:,
@@ -32,6 +35,7 @@ module Featury
32
35
  def call!(
33
36
  action:,
34
37
  incoming_arguments:,
38
+ collection_of_callbacks:,
35
39
  collection_of_resources:,
36
40
  collection_of_conditions:,
37
41
  collection_of_features:,
@@ -39,6 +43,7 @@ module Featury
39
43
  )
40
44
  @action = action
41
45
  @incoming_arguments = incoming_arguments
46
+ @collection_of_callbacks = collection_of_callbacks
42
47
  @collection_of_resources = collection_of_resources
43
48
  @collection_of_conditions = collection_of_conditions
44
49
  @collection_of_features = collection_of_features
@@ -11,7 +11,7 @@ module Featury
11
11
  end
12
12
 
13
13
  def list
14
- map { |feature| :"#{feature.prefix}_#{feature.name}" }
14
+ @list ||= map { |feature| :"#{feature.prefix}_#{feature.name}" }
15
15
  end
16
16
  end
17
17
  end
@@ -17,15 +17,32 @@ module Featury
17
17
  private
18
18
 
19
19
  def prefix(prefix)
20
- @prefix = prefix
20
+ self.feature_prefix = prefix
21
21
  end
22
22
 
23
23
  def features(*names)
24
24
  names.each do |name|
25
- collection_of_features << Feature.new(@prefix, name)
25
+ collection_of_features << Feature.new(feature_prefix, name)
26
26
  end
27
27
  end
28
28
 
29
+ def feature_prefix=(value)
30
+ @feature_prefix = value
31
+ end
32
+
33
+ def feature_prefix
34
+ @feature_prefix || default_feature_prefix
35
+ end
36
+
37
+ def default_feature_prefix
38
+ @default_feature_prefix ||=
39
+ name.underscore
40
+ .gsub(/([a-z])(\d+)/, '\1_\2')
41
+ .gsub(/(\d+)([a-z])/, '\1_\2')
42
+ .tr("/", "_")
43
+ .to_sym
44
+ end
45
+
29
46
  def collection_of_features
30
47
  @collection_of_features ||= Collection.new
31
48
  end
@@ -5,7 +5,7 @@ module Featury
5
5
  MAJOR = 1
6
6
  MINOR = 0
7
7
  PATCH = 0
8
- PRE = "rc12"
8
+ PRE = "rc14"
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
11
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: featury
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc12
4
+ version: 1.0.0.rc14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov
@@ -160,6 +160,11 @@ files:
160
160
  - lib/featury/actions/service/factory.rb
161
161
  - lib/featury/actions/workspace.rb
162
162
  - lib/featury/base.rb
163
+ - lib/featury/callbacks/callback.rb
164
+ - lib/featury/callbacks/collection.rb
165
+ - lib/featury/callbacks/dsl.rb
166
+ - lib/featury/callbacks/service.rb
167
+ - lib/featury/callbacks/workspace.rb
163
168
  - lib/featury/conditions/collection.rb
164
169
  - lib/featury/conditions/condition.rb
165
170
  - lib/featury/conditions/dsl.rb