feature_toggles 1.0.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: []