feature_toggles 1.0.0 → 1.2.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: ced315883f27c7dfa71e43d3b04a2e0c6111d7e3ab24ebb2d96b309880349abc
4
- data.tar.gz: 2567a6b58344a5b1b05c2380374ef85e1325119a243af0310003b2ad170838bf
3
+ metadata.gz: de5be65d90b2486463f37deb065af002bf6ccb012a2d0430fb26e29ba50349c9
4
+ data.tar.gz: 47699f6cb92c4e8f438132964c17070f7b0af6510cf8d16fd80f41232462be65
5
5
  SHA512:
6
- metadata.gz: f3d9058efacee049c3feed1bc5878e3ba301d2e1d424954e8f871e802d2e31f110503a870b6f7dc90a92a84cca9012e02cacc5eb8c3ca52c2af912547fc05e20
7
- data.tar.gz: 6f80548653e6f6f6792ef1a0b42c385d9def25c730a91d10d41e3b1d13d49442ecd8e799d7a0d66ac3e591366f207c7723b685b314a2ce670251ef5c0495f9c3
6
+ metadata.gz: 68ecaccea419ea6ac0080419f68f16e2c9d22a849128f5889eb3600dd254dea0c0ec220c42223079edcff316dd0e34854270f6200a8d85a756019a3baccd60b1
7
+ data.tar.gz: a3e5227b603b3ddc1fe09715479aa390c4cae2df7a92317b2f529b5d6c55ee58d843810e25111fb113623dc5ab1a6f807d719d07be81848f8f048e3dcafdbde0
data/README.md CHANGED
@@ -73,10 +73,10 @@ end
73
73
 
74
74
  **Step 1. Define features**
75
75
 
76
- Features from file `<rails-root-or-engine>/config/initializers/features.rb` are loaded by convention.
76
+ Features from file `<rails-root-or-engine>/config/features.rb` are loaded by convention.
77
77
 
78
78
  ```ruby
79
- # config/initializers/features.rb
79
+ # config/features.rb
80
80
  env "FEATURE"
81
81
 
82
82
  feature :chat do |user: nil|
@@ -123,6 +123,24 @@ class ChatController < ApplicationController
123
123
  end
124
124
  ```
125
125
 
126
+ ### Metadata
127
+
128
+ You can add arbitrary metadata to features:
129
+
130
+ ```ruby
131
+ feature :manual_quantity_backsync, icon: :updated, description: "Manual quantity sync for imported products" do |user: nil|
132
+ !!user&.features&.fetch("manual_quantity_backsync", false)
133
+ end
134
+ ```
135
+
136
+ That metadata can be later programmatically accessed and exposed into admin panels, API documentation, etc.
137
+
138
+ ```ruby
139
+ Rails.features.first.metadata
140
+ # => { icon: :updated, description: "Manual quantity sync for imported products" }
141
+ ```
142
+
143
+
126
144
  ## Development
127
145
 
128
146
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FeatureToggles
4
+ class Feature
5
+ def initialize(name, resolver, **metadata)
6
+ @name = name
7
+ @resolver = resolver
8
+ @metadata = metadata
9
+ end
10
+
11
+ attr_reader :name, :resolver, :metadata
12
+
13
+ def [](key)
14
+ @metadata[key]
15
+ end
16
+ end
17
+ end
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "proxy"
4
+ require_relative "feature"
4
5
 
5
6
  module FeatureToggles
6
7
  class Mechatronic
8
+ include Enumerable
9
+
7
10
  # Which env variables should be considered truthy
8
- POSSIBLE_ENABLING_VALUES = %w(true on yes 1).freeze
11
+ POSSIBLE_ENABLING_VALUES = %w[true on yes 1].freeze
9
12
 
10
13
  def initialize(definition_file_paths = nil, &block)
11
14
  @features = {}
@@ -14,41 +17,49 @@ module FeatureToggles
14
17
  instance_eval(File.read(file), file)
15
18
  end
16
19
 
17
- instance_eval(&block) if block_given?
20
+ instance_eval(&block) if block
18
21
  end
19
22
 
20
23
  def env(val)
21
24
  @env_prefix = val
22
25
  end
23
26
 
24
- def feature(name, &block)
27
+ def feature(name, **metadata, &block)
25
28
  raise(ArgumentError, "Flag #{name} already exists") if @features.key?(name)
26
29
 
27
- features[name] = block
30
+ features[name] = Feature.new(name, block, **metadata)
28
31
  end
29
32
 
30
33
  def names
31
34
  features.keys
32
35
  end
33
36
 
34
- def enabled?(feature, *args)
35
- enabled_globally?(feature) || !!features.fetch(feature).call(*args)
37
+ def enabled?(feature, *args, **kwargs)
38
+ enabled_globally?(feature) || !!features.fetch(feature).resolver.call(*args, **kwargs)
36
39
  end
37
40
 
38
- def for(*args)
39
- Proxy.new(self, *args)
41
+ def for(*args, **kwargs)
42
+ Proxy.new(self, *args, **kwargs)
40
43
  end
41
44
 
42
- def to_a(*args)
45
+ def to_a(*args, **kwargs)
43
46
  names.map do |feature|
44
- {feature: feature, enabled: enabled?(feature, *args)}
47
+ {feature: feature, enabled: enabled?(feature, *args, **kwargs)}
45
48
  end
46
49
  end
47
50
 
48
- def to_h(*args)
49
- Hash[features.map do |feature, _|
50
- [feature, enabled?(feature, *args)]
51
- end]
51
+ def to_h(*args, **kwargs)
52
+ features.map do |feature, _|
53
+ [feature, enabled?(feature, *args, **kwargs)]
54
+ end.to_h
55
+ end
56
+
57
+ def each
58
+ if block_given?
59
+ features.values.each { |f| yield f }
60
+ else
61
+ features.values.to_enum
62
+ end
52
63
  end
53
64
 
54
65
  private
@@ -2,25 +2,26 @@
2
2
 
3
3
  module FeatureToggles
4
4
  class Proxy
5
- def initialize(toggle, *args)
5
+ def initialize(toggle, *args, **kwargs)
6
6
  @toggle = toggle
7
7
  @args = args
8
+ @kwargs = kwargs
8
9
  end
9
10
 
10
11
  def enabled?(feature)
11
- toggle.enabled?(feature, *args)
12
+ toggle.enabled?(feature, *args, **kwargs)
12
13
  end
13
14
 
14
15
  def to_a
15
- toggle.to_a(*args)
16
+ toggle.to_a(*args, **kwargs)
16
17
  end
17
18
 
18
19
  def to_h
19
- toggle.to_h(*args)
20
+ toggle.to_h(*args, **kwargs)
20
21
  end
21
22
 
22
23
  private
23
24
 
24
- attr_reader :toggle, :args
25
+ attr_reader :toggle, :args, :kwargs
25
26
  end
26
27
  end
@@ -26,7 +26,7 @@ module FeatureToggles
26
26
  file = ::Rails.root.join("config", "features.rb")
27
27
  paths << file.to_s if file.exist?
28
28
 
29
- Rails.application.config.features = FeatureToggles.build(paths)
29
+ Rails.application.config.features = FeatureToggles.build(paths.uniq)
30
30
  end
31
31
  end
32
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FeatureToggles
4
- VERSION = "1.0.0"
4
+ VERSION = "1.2.1"
5
5
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feature_toggles
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Merkushin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-21 00:00:00.000000000 Z
11
+ date: 2022-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.16'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.16'
27
27
  - !ruby/object:Gem::Dependency
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.1'
33
+ version: '1.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.1'
40
+ version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry-byebug
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,43 +58,43 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.0'
75
+ version: '3.10'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.0'
82
+ version: '3.10'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rubocop
84
+ name: standard
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.58'
89
+ version: '1.1'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.58'
97
- description:
96
+ version: '1.1'
97
+ description:
98
98
  email:
99
99
  - merkushin.m.s@gmail.com
100
100
  executables: []
@@ -104,6 +104,7 @@ files:
104
104
  - LICENSE.txt
105
105
  - README.md
106
106
  - lib/feature_toggles.rb
107
+ - lib/feature_toggles/feature.rb
107
108
  - lib/feature_toggles/mechatronic.rb
108
109
  - lib/feature_toggles/proxy.rb
109
110
  - lib/feature_toggles/railtie.rb
@@ -113,24 +114,23 @@ licenses:
113
114
  - MIT
114
115
  metadata:
115
116
  allowed_push_host: https://rubygems.org
116
- post_install_message:
117
+ post_install_message:
117
118
  rdoc_options: []
118
119
  require_paths:
119
120
  - lib
120
121
  required_ruby_version: !ruby/object:Gem::Requirement
121
122
  requirements:
122
- - - ">="
123
+ - - ">"
123
124
  - !ruby/object:Gem::Version
124
- version: '0'
125
+ version: '2.5'
125
126
  required_rubygems_version: !ruby/object:Gem::Requirement
126
127
  requirements:
127
128
  - - ">="
128
129
  - !ruby/object:Gem::Version
129
130
  version: '0'
130
131
  requirements: []
131
- rubyforge_project:
132
- rubygems_version: 2.7.6
133
- signing_key:
132
+ rubygems_version: 3.2.32
133
+ signing_key:
134
134
  specification_version: 4
135
135
  summary: This gem provides a mechanism for pending features.
136
136
  test_files: []