this_feature-adapters-flipper 0.3.0 → 0.5.2

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: 1a4a261fc36bd82e31aecd8f83fc399e50eca40fdf1b639b10ce3c5d819f6aa9
4
- data.tar.gz: 6053c41648e337f13a9817d0f5c6134755ecb7b8b4f3364d9b11ef761ef4aabf
3
+ metadata.gz: 4de6acf45dc7581500f737401158c90b6e2da6b6193c33a19c6e7c15378d8f8a
4
+ data.tar.gz: 4bf56af16928ae0d03a827e3039b404cc03e94f3ceb0d32a0f3790981381feab
5
5
  SHA512:
6
- metadata.gz: 24ad8ced3e7e4f13f878943f49cd4f2bba8db2a6e543805b9eb29d8e7bd4d6736d9fd73525c1bcfdc4c20e617b5156f5d6d9561f38fc6ba5add72d7d09367e28
7
- data.tar.gz: 4d75aa7090b18b05b0ced212f315c92bce510793959fd79c83107507dc285199f31db6c4e0481c62e4c797548de5ae165fa2c46b02fd8bb9535822744f83dd04
6
+ metadata.gz: 52d87427a549c8f8e1c51c1df420fc9df37c2c929b62f1644a13ee0dd8e5ee7c4d19c759d58962589853f473e3e88ef087c4544d4f8b98527abd048d49a82504
7
+ data.tar.gz: c64ce30d84f15a31f09241d66fa8a053056e1f12ffa730a10d1cd9f54d943786424fb0ddbaaff4afe3c3a4a95200e99435d349193a273d5ac327a88d437b40b9
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec name: "this_feature"
4
4
  gemspec name: "this_feature-adapters-flipper"
5
+ gemspec name: "this_feature-adapters-split_io"
@@ -1,10 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- this_feature (0.3.0)
5
- this_feature-adapters-flipper (0.3.0)
4
+ this_feature (0.5.0)
5
+ this_feature-adapters-flipper (0.5.0)
6
6
  flipper (~> 0.16)
7
7
  flipper-active_record (~> 0.16)
8
+ this_feature
9
+ this_feature-adapters-split_io (0.5.0)
10
+ splitclient-rb
11
+ this_feature
8
12
 
9
13
  GEM
10
14
  remote: https://rubygems.org/
@@ -23,20 +27,30 @@ GEM
23
27
  byebug (11.1.2)
24
28
  coderay (1.1.2)
25
29
  concurrent-ruby (1.1.6)
30
+ connection_pool (2.2.3)
26
31
  database_cleaner (1.8.4)
27
32
  database_cleaner-active_record (1.8.0)
28
33
  activerecord
29
34
  database_cleaner (~> 1.8.0)
30
35
  diff-lcs (1.3)
31
- flipper (0.18.0)
32
- flipper-active_record (0.18.0)
36
+ faraday (1.0.1)
37
+ multipart-post (>= 1.2, < 3)
38
+ flipper (0.19.0)
39
+ flipper-active_record (0.19.0)
33
40
  activerecord (>= 5.0, < 7)
34
- flipper (~> 0.18.0)
41
+ flipper (~> 0.19.0)
35
42
  gem-release (2.1.1)
43
+ hitimes (1.3.1)
36
44
  i18n (1.8.5)
37
45
  concurrent-ruby (~> 1.0)
46
+ json (2.3.1)
47
+ jwt (2.2.2)
48
+ lru_redux (1.1.0)
38
49
  method_source (1.0.0)
39
50
  minitest (5.14.1)
51
+ multipart-post (2.1.1)
52
+ net-http-persistent (4.0.0)
53
+ connection_pool (~> 2.2)
40
54
  pry (0.13.1)
41
55
  coderay (~> 1.1)
42
56
  method_source (~> 1.0)
@@ -44,6 +58,7 @@ GEM
44
58
  byebug (~> 11.0)
45
59
  pry (~> 0.13.0)
46
60
  rake (13.0.1)
61
+ redis (4.2.2)
47
62
  rspec (3.9.0)
48
63
  rspec-core (~> 3.9.0)
49
64
  rspec-expectations (~> 3.9.0)
@@ -57,6 +72,18 @@ GEM
57
72
  diff-lcs (>= 1.2.0, < 2.0)
58
73
  rspec-support (~> 3.9.0)
59
74
  rspec-support (3.9.2)
75
+ socketry (0.5.1)
76
+ hitimes (~> 1.2)
77
+ splitclient-rb (7.1.3)
78
+ concurrent-ruby (~> 1.0)
79
+ faraday (>= 0.8)
80
+ json (>= 1.8)
81
+ jwt (>= 2.2.1)
82
+ lru_redux
83
+ net-http-persistent (>= 2.9)
84
+ redis (>= 3.2)
85
+ socketry (~> 0.5.1)
86
+ thread_safe (>= 0.3)
60
87
  sqlite3 (1.4.2)
61
88
  thread_safe (0.3.6)
62
89
  tzinfo (1.2.7)
@@ -76,6 +103,7 @@ DEPENDENCIES
76
103
  sqlite3
77
104
  this_feature!
78
105
  this_feature-adapters-flipper!
106
+ this_feature-adapters-split_io!
79
107
 
80
108
  BUNDLED WITH
81
109
  2.1.4
data/README.md CHANGED
@@ -1,59 +1,69 @@
1
1
  # ThisFeature
2
2
 
3
- The purpose of ThisFeature is to have one way to use feature flags
3
+ **A common interface to interact with many feature flag providers.**
4
4
 
5
- ## Installation
5
+ Can be used to more easily migrate among providers.
6
+
7
+ If your code uses ThisFeature,
8
+ then you can just swap out the adapter without having to do a bunch of find-and-replace.
6
9
 
7
- Add this line to your application's `Gemfile`:
10
+ ## Installation
8
11
 
9
12
  ```ruby
10
13
  gem 'this_feature'
11
14
  ```
12
15
 
13
- And then execute:
16
+ ## Configuration
14
17
 
15
- ```sh
16
- bundle
18
+ ```ruby
19
+ # config/initializers/this_feature.rb
20
+ require 'this_feature'
21
+ require 'this_feature/adapters/memory'
22
+
23
+ ThisFeature.configure do |config|
24
+ adapter = ThisFeature::Adapters::Memory.new
25
+ config.adapters = [adapter]
26
+ config.default_adapter = adapter
27
+ end
17
28
  ```
18
29
 
19
- Or install it yourself as:
20
-
21
- ```sh
22
- gem install feature
23
- ```
30
+ **NOTE**: When searching for the presence of a flag, adapters are queried in order. The default adapter is the fallback adapter used when a flag isn't present in any of the adapters.
24
31
 
25
32
  ## Usage
26
33
 
27
- ### Currently
28
-
29
- Currently, the only available adapter is `Flipper`.
30
- We will update this document when more are added.
31
-
32
- To set it up, put this in an initializer file:
34
+ ### Flags
33
35
 
34
36
  ```ruby
35
- ThisFeature.set_adapters([ThisFeature::Adapters::FlipperAdapter])
37
+ ThisFeature.flag('flag_name').on? # is the flag is turned on?
38
+ ThisFeature.flag('flag_name').off? # is the flag is turned off?
39
+ ThisFeature.flag('flag_name').control? # is the adapter is using the control?
40
+ ThisFeature.flag('flag_name').present? # is the flag set at all?
41
+ ThisFeature.default_adapter # access the default adapter directly if needed
36
42
  ```
37
43
 
38
- This `set_adapters` will internally call the `.setup` method on the `FlipperAdapter`, which performs the Flipper initialization.
44
+ ### Context
39
45
 
40
- Then you can call `ThisFeature.enabled?("flag name")`.
46
+ You can also pass a context to the flag, many feature flagging systems support this.
41
47
 
42
- It will iterate through the adapters until one of them returns `true`/`false`.
48
+ ```ruby
49
+ ThisFeature.flag('flag_name', context: current_user).on?
50
+ ```
43
51
 
44
- A context (`User` or `Org`) can be passed in the arguments to `enabled?` as well. `ThisFeature.enabled?(:flag_name, Current.user)`
52
+ ### Data
45
53
 
46
- ### Planned
54
+ In case context is not sufficient, you can also pass a data hash.
47
55
 
48
- Create an initializer file in your Rails app:
56
+ ```ruby
57
+ ThisFeature.flag('flag_name', context: context, data: { org_id: 1 }).on?
58
+ ```
49
59
 
50
- `/config/initializers/this_feature.rb`
60
+ ## Available Adapters
51
61
 
52
- And set your list of adapters, _ordered by priority_. For example:
62
+ These adapters do behave slightly differently, so make sure to read the following docs:
53
63
 
54
- ```ruby
55
- ThisFeature.adapters = [SplitIO Flipper]
56
- ```
64
+ - [Flipper adapter](./docs/flipper.md)
65
+ - [Split.io adapter](./docs/splitio.md)
66
+ - [Memory adapter](./docs/memory.md) - **designed for use in tests**
57
67
 
58
68
  ## Development
59
69
 
@@ -64,6 +74,11 @@ You can run the tests with these commands in your Terminal:
64
74
  bundle install && bundle exec rspec
65
75
  ```
66
76
 
77
+ To write a new adapter, check the [Guide](./docs/writing_an_adapter.md).
78
+
67
79
  ## License
68
80
 
69
81
  ThisFeature is released under the [MIT License](https://choosealicense.com/licenses/mit).
82
+
83
+
84
+
@@ -13,19 +13,19 @@ class ThisFeature
13
13
 
14
14
  def self.adapter_for(flag_name, context: nil, data: {})
15
15
  matching_adapter = adapters.find do |adapter|
16
- adapter.present?(flag_name, context: context, data: data)
16
+ adapter.present?(flag_name)
17
17
  end
18
18
 
19
19
  matching_adapter || configuration.default_adapter
20
20
  end
21
21
 
22
- # Configuration
23
-
24
22
  def self.configuration
25
23
  @configuration ||= Configuration.new
26
24
  end
27
25
 
28
26
  def self.configure
27
+ @configuration = Configuration.new
28
+
29
29
  yield(configuration)
30
30
 
31
31
  configuration.init
@@ -35,4 +35,7 @@ class ThisFeature
35
35
  configuration.adapters
36
36
  end
37
37
 
38
+ def self.test_adapter
39
+ configuration.test_adapter
40
+ end
38
41
  end
@@ -1,34 +1,21 @@
1
1
  class ThisFeature
2
2
  module Adapters
3
3
  class Base
4
-
5
- def self.setup
6
- raise UnimplementedError.new(self, __method__)
7
- end
8
-
9
- def self.present?(flag_name)
10
- raise UnimplementedError.new(self, __method__)
11
- end
12
-
13
- def self.on?(flag_name, context: nil, data: {})
14
- raise UnimplementedError.new(self, __method__)
15
- end
16
-
17
- def self.off?(flag_name, context: nil, data: {})
4
+ def present?(flag_name)
18
5
  raise UnimplementedError.new(self, __method__)
19
6
  end
20
7
 
21
- def self.on!(flag_name, context: nil, data: {})
8
+ def on?(flag_name, context: nil, data: {})
22
9
  raise UnimplementedError.new(self, __method__)
23
10
  end
24
11
 
25
- def self.off!(flag_name, context: nil, data: {})
12
+ def off?(flag_name, context: nil, data: {})
26
13
  raise UnimplementedError.new(self, __method__)
27
14
  end
28
15
 
29
16
  # OPTIONAL method
30
17
  # check to see if a control is being used
31
- def self.control?(flag_name, context: nil, data: {})
18
+ def control?(flag_name, context: nil, data: {})
32
19
  false
33
20
  end
34
21
  end
@@ -4,48 +4,38 @@ require "flipper/adapters/active_record"
4
4
  class ThisFeature
5
5
  module Adapters
6
6
  class Flipper < Base
7
+ attr_reader :client
7
8
 
8
- def self.setup(flipper = nil)
9
- return @flipper = flipper unless flipper.nil?
10
-
11
- @flipper = ::Flipper
12
-
13
- ::Flipper.configure do |config|
14
- config.default do
15
- adapter = ::Flipper::Adapters::ActiveRecord.new
16
- ::Flipper.new(adapter)
17
- end
18
- end
9
+ def initialize(client: nil)
10
+ @client = client || default_flipper_adapter
19
11
  end
20
12
 
21
- def self.present?(flag_name)
22
- flipper[flag_name].exist?
13
+ def present?(flag_name)
14
+ client[flag_name].exist?
23
15
  end
24
16
 
25
- def self.on?(flag_name, context: nil, data: {})
26
- return unless present?(flag_name)
27
-
28
- flipper[flag_name].enabled?(*[context].compact)
17
+ def control?(flag_name, **kwargs)
18
+ !present?(flag_name)
29
19
  end
30
20
 
31
- def self.off?(flag_name, context: nil, data: {})
32
- on_result = on?(flag_name, context: context)
33
-
34
- return if on_result.nil?
35
-
36
- !on_result
21
+ def on?(flag_name, context: nil, data: {})
22
+ client[flag_name].enabled?(*[context].compact)
37
23
  end
38
24
 
39
- def self.on!(flag_name, context: nil, data: {})
40
- flipper[flag_name].enable(*[context].compact)
25
+ def off?(flag_name, context: nil, data: {})
26
+ !on?(flag_name, context: context)
41
27
  end
42
28
 
43
- def self.off!(flag_name, context: nil, data: {})
44
- flipper[flag_name].disable(*[context].compact)
45
- end
29
+ private
46
30
 
47
- def self.flipper
48
- @flipper
31
+ def default_flipper_adapter
32
+ ::Flipper.configure do |config|
33
+ config.default do
34
+ adapter = ::Flipper::Adapters::ActiveRecord.new
35
+ ::Flipper.new(adapter)
36
+ end
37
+ end
38
+ ::Flipper
49
39
  end
50
40
  end
51
41
  end
@@ -2,20 +2,19 @@ class ThisFeature
2
2
  module Adapters
3
3
  class Memory < Base
4
4
 
5
- def self.setup(context_id_method: :id)
6
- @context_id_method = context_id_method
5
+ def initialize(context_key_method: nil)
6
+ @context_key_method = context_key_method
7
7
  end
8
8
 
9
- def self.clear
9
+ def clear
10
10
  storage.clear
11
11
  end
12
12
 
13
- def self.present?(flag_name)
13
+ def present?(flag_name)
14
14
  !storage[flag_name].nil?
15
15
  end
16
16
 
17
- def self.on?(flag_name, context: nil, data: {})
18
- # binding.pry
17
+ def on?(flag_name, context: nil, data: {})
19
18
  return unless present?(flag_name)
20
19
 
21
20
  flag_data = storage[flag_name]
@@ -25,10 +24,10 @@ class ThisFeature
25
24
 
26
25
  flag_data[:contexts] ||= {}
27
26
 
28
- !!flag_data[:contexts][context.send(@context_id_method)]
27
+ !!flag_data[:contexts][context_key(context)]
29
28
  end
30
29
 
31
- def self.off?(flag_name, context: nil, data: {})
30
+ def off?(flag_name, context: nil, data: {})
32
31
  on_result = on?(flag_name, context: context)
33
32
 
34
33
  return if on_result.nil?
@@ -36,27 +35,37 @@ class ThisFeature
36
35
  !on_result
37
36
  end
38
37
 
39
- def self.on!(flag_name, context: nil, data: {})
38
+ def on!(flag_name, context: nil, data: {})
40
39
  storage[flag_name] ||= {}
41
40
 
42
41
  return storage[flag_name][:global] = true if context.nil?
43
42
 
44
43
  storage[flag_name][:contexts] ||= {}
45
- storage[flag_name][:contexts][context.send(@context_id_method)] = true
44
+ storage[flag_name][:contexts][context_key(context)] = true
46
45
  end
47
46
 
48
- def self.off!(flag_name, context: nil, data: {})
47
+ def off!(flag_name, context: nil, data: {})
49
48
  storage[flag_name] ||= {}
50
49
 
51
50
  return storage[flag_name][:global] = false if context.nil?
52
51
 
53
52
  storage[flag_name][:contexts] ||= {}
54
- storage[flag_name][:contexts][context.send(@context_id_method)] = false
53
+ storage[flag_name][:contexts][context_key(context)] = false
55
54
  end
56
55
 
57
- def self.storage
56
+ def storage
58
57
  @storage ||= {}
59
58
  end
59
+
60
+ private
61
+
62
+ attr_reader :context_key_method
63
+
64
+ def context_key(context)
65
+ return context if context_key_method.nil?
66
+
67
+ context.send(context_key_method)
68
+ end
60
69
  end
61
70
  end
62
71
  end
@@ -0,0 +1,52 @@
1
+ require 'splitclient-rb'
2
+
3
+ class ThisFeature
4
+ module Adapters
5
+ class SplitIo < Base
6
+ # used as treatment key when none is given, it's required by split
7
+ UNDEFINED_KEY = 'undefined_key'
8
+
9
+ def initialize(client: nil)
10
+ @client = client || default_split_client
11
+
12
+ @client.block_until_ready
13
+ end
14
+
15
+ def present?(flag_name)
16
+ !control?(flag_name)
17
+ end
18
+
19
+ def control?(flag_name, context: UNDEFINED_KEY, data: {})
20
+ treatment(flag_name, context: context, data: data).include?('control')
21
+ end
22
+
23
+ def on?(flag_name, context: UNDEFINED_KEY, data: {})
24
+ treatment(flag_name, context: context, data: data).eql?('on')
25
+ end
26
+
27
+ def off?(flag_name, context: UNDEFINED_KEY, data: {})
28
+ treatment(flag_name, context: context, data: data).eql?('off')
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :client
34
+
35
+ def treatment(flag_name, context: UNDEFINED_KEY, data: {})
36
+ key = if context.nil?
37
+ UNDEFINED_KEY
38
+ elsif context.respond_to?(:to_s)
39
+ context.to_s
40
+ else
41
+ context
42
+ end
43
+
44
+ client.get_treatment(key, flag_name, data)
45
+ end
46
+
47
+ def default_split_client
48
+ SplitIoClient::SplitFactory.new(ENV.fetch('SPLIT_IO_AUTH_KEY')).client
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,17 +1,16 @@
1
-
2
1
  class ThisFeature
3
2
  class Configuration
4
- attr_writer :adapters, :default_adapter
3
+ attr_writer :adapters, :default_adapter, :test_adapter
5
4
 
6
5
  def init
7
6
  validate_adapters!
8
-
9
- adapters.each(&:setup)
10
7
  end
11
8
 
12
9
  def validate_adapters!
10
+ raise(NoAdaptersError.new) unless adapters.any?
11
+
13
12
  adapters.each do |adapter|
14
- raise BadAdapterError.new(adapter) unless adapter < Adapters::Base
13
+ raise BadAdapterError.new(adapter) unless adapter.class < Adapters::Base
15
14
  end
16
15
  end
17
16
 
@@ -22,5 +21,9 @@ class ThisFeature
22
21
  def default_adapter
23
22
  @default_adapter ||= adapters.first
24
23
  end
24
+
25
+ def test_adapter
26
+ @test_adapter ||= Adapters::Memory.new
27
+ end
25
28
  end
26
29
  end
@@ -3,20 +3,20 @@ class ThisFeature
3
3
  class Error < StandardError; end
4
4
 
5
5
  class UnimplementedError < Error
6
- def initialize(klass, fn_name)
7
- super("class #{klass.name} doesnt implement method .#{fn_name}")
6
+ def initialize(adapter_instance, fn_name)
7
+ super("class #{adapter_instance.class.name} doesnt implement method .#{fn_name}")
8
8
  end
9
9
  end
10
10
 
11
11
  class BadAdapterError < Error
12
- def initialize(adapter)
13
- super("adapter #{adapter.name} doesn't inherit from ThisFeature::Adapters::Base")
12
+ def initialize(adapter_instance)
13
+ super("adapter #{adapter_instance.class.name} doesn't inherit from #{ThisFeature::Adapters::Base.name}")
14
14
  end
15
15
  end
16
16
 
17
- class NoWriteAdapter < Error
17
+ class NoAdaptersError < Error
18
18
  def initialize
19
- super("Use the `ThisFeature.write_adapter=` setter before calling #enable or #disable")
19
+ super("No adapters configured.")
20
20
  end
21
21
  end
22
22
 
@@ -20,13 +20,5 @@ class ThisFeature
20
20
  def control?
21
21
  adapter.control?(flag_name, context: context, data: data)
22
22
  end
23
-
24
- def on!
25
- adapter.on!(flag_name, context: context, data: data)
26
- end
27
-
28
- def off!
29
- adapter.off!(flag_name, context: context, data: data)
30
- end
31
23
  end
32
24
  end
@@ -1,3 +1,3 @@
1
1
  class ThisFeature
2
- VERSION = "0.3.0"
2
+ VERSION = "0.5.2"
3
3
  end
data/memory CHANGED
Binary file
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.platform = Gem::Platform::RUBY
19
19
  s.require_paths = ['lib']
20
20
 
21
+ s.add_runtime_dependency "this_feature"
21
22
  s.add_runtime_dependency "flipper", "~> 0.16"
22
23
  s.add_runtime_dependency "flipper-active_record", "~> 0.16"
23
24
  end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+
5
+ require 'this_feature/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'this_feature-adapters-split_io'
9
+ s.version = ThisFeature::VERSION
10
+ s.authors = ['Max Pleaner', 'Matt Fong']
11
+ s.email = ['maxpleaner@gmail.com', 'matthewjf@gmail.com']
12
+ s.homepage = 'http://hover.to'
13
+ s.licenses = ['MIT']
14
+ s.summary = '[summary]'
15
+ s.description = '[description]'
16
+
17
+ s.files = Dir.glob('{bin/*,lib/**/*,[A-Z]*}')
18
+ s.platform = Gem::Platform::RUBY
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_runtime_dependency "this_feature"
22
+ s.add_runtime_dependency "splitclient-rb"
23
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: this_feature-adapters-flipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Pleaner
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-26 00:00:00.000000000 Z
11
+ date: 2020-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: this_feature
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: flipper
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,18 +72,20 @@ files:
58
72
  - lib/this_feature/adapters/base.rb
59
73
  - lib/this_feature/adapters/flipper.rb
60
74
  - lib/this_feature/adapters/memory.rb
75
+ - lib/this_feature/adapters/split_io.rb
61
76
  - lib/this_feature/configuration.rb
62
77
  - lib/this_feature/errors.rb
63
78
  - lib/this_feature/flag.rb
64
79
  - lib/this_feature/version.rb
65
80
  - memory
66
81
  - this_feature-adapters-flipper.gemspec
82
+ - this_feature-adapters-split_io.gemspec
67
83
  - this_feature.gemspec
68
84
  homepage: http://hover.to
69
85
  licenses:
70
86
  - MIT
71
87
  metadata: {}
72
- post_install_message:
88
+ post_install_message:
73
89
  rdoc_options: []
74
90
  require_paths:
75
91
  - lib
@@ -85,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
101
  version: '0'
86
102
  requirements: []
87
103
  rubygems_version: 3.1.2
88
- signing_key:
104
+ signing_key:
89
105
  specification_version: 4
90
106
  summary: "[summary]"
91
107
  test_files: []