this_feature-adapters-flipper 0.3.0 → 0.5.2

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: 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: []