roda-contrib 0.1.0 → 0.2.0

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
  SHA1:
3
- metadata.gz: bb288c9a14fff9c8e20f4c634d98dbb978d16665
4
- data.tar.gz: 1796bec3454a2debbebfb7fca336b7eae91877f5
3
+ metadata.gz: 02c8c0cc04c5707343034068120ae9b8ed70cf90
4
+ data.tar.gz: af47f15ba933ef6a3c0dc06219a6e1a0a1f2d7dd
5
5
  SHA512:
6
- metadata.gz: dc3874788ae3fd3a0e937f7b45983993c07e600ab2da16158e929a7165d9f3ade248b774f200d4a4bee09845f52f6a5e09e0a951c68f86f46f6f5d1af7290c63
7
- data.tar.gz: a392f95361ea4f3d54384f5f968a09d7200ca3bad051b5e942c07a3dc229414d715b39bac5708570e02b8b78eac38ba7c6236457ce91f577dd32155601b34905
6
+ metadata.gz: 309ecb8592c05a838d39658cfad67c1d121646cc64ad0d7c54ade11ce5fadfacfb395743ddffe38d76a4de02287a401488d40c48abb965182b7cff2a59caeaa8
7
+ data.tar.gz: 5b9127a06f6c68c9cb3050713c923263e4cae9fdb01477b05ad1cc2238c4fc0a046a2ecfea7f2a1ef97ce090bb16f02d6a75023240b0071baf8acc8a1ba183a2
data/.yardopts ADDED
@@ -0,0 +1,6 @@
1
+ --no-cache
2
+ --no-save
3
+ --output-dir www
4
+ lib/**/*.rb
5
+ -
6
+ LICENSE.txt
data/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ = 0.2.0(2017-6-6)
2
+ * add load_all plugin
3
+ * add multi_dispatch plugin
4
+ * add csrf plugin
5
+ * add CHANGELOG
6
+
7
+ = 0.1.0(2017-6-5)
8
+ * initial commit
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # RodaContrib
2
2
 
3
- The roda-contrib gem is my personal collection of plugins working with Roda(the Routing tree toolkit).
3
+ The roda-contrib gem is my personal collection of plugins working with Roda(the
4
+ Routing tree toolkit).
4
5
 
5
6
  ## Installation
6
7
 
@@ -20,17 +21,36 @@ Or install it yourself as:
20
21
 
21
22
  ## Usage
22
23
 
23
- <!-- TODO: Write usage instructions here -->
24
+ Currently, the roda-contrib gem ships 3 plugins:
25
+
26
+ * load\_all
27
+ * multi\_dispatch
28
+ * csrf
29
+
30
+ When loading plugins from this gem, you should append the 'contrib' to the
31
+ symbol to load it. For example, if you want to use the multi\_dispatch plugin:
32
+
33
+ ```ruby
34
+ class App < Roda
35
+ plugin :contrib_multi_dispatch
36
+ end
37
+ ```
38
+
39
+ For details of the each plugin, please refer to the documentation or the code.
24
40
 
25
41
  ## Development
26
42
 
27
- 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.
43
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
44
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
45
+ prompt that will allow you to experiment.
28
46
 
29
47
  ## Contributing
30
48
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/luciusgone/roda-contrib.
49
+ Bug reports and pull requests are welcome on GitHub at
50
+ https://github.com/luciusgone/roda-contrib.
32
51
 
33
52
 
34
53
  ## License
35
54
 
36
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
55
+ The gem is available as open source under the terms of the
56
+ [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,6 +1,11 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'yard'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
6
 
7
+ YARD::Rake::YardocTask.new do |t|
8
+ t.stats_options = ['--list-undoc']
9
+ end
10
+
6
11
  task :default => :spec
@@ -0,0 +1,3 @@
1
+ = '0.1.0' release note
2
+
3
+ Initial release
@@ -0,0 +1,19 @@
1
+ = 0.2.0 release note
2
+
3
+ == New Features
4
+
5
+ * add _contrib_load_all_ plugin.
6
+ This plugin helps writing clean code requiring different part of the roda
7
+ app.
8
+
9
+ * add _contrib_multi_dispatch_ plugin.
10
+ This plugin helps seperating different logics by delegating request to an
11
+ external object.
12
+
13
+ * add _contrib_csrf_ plugin.
14
+ Apart from the official csrf plugin, It exposes only one interface to make
15
+ the main roda app a bit clean.
16
+
17
+ * add RodaContrib::Action
18
+ This mixin is the main way for roda-contrib to package plugable business
19
+ logic.
@@ -0,0 +1,30 @@
1
+ require 'forwardable'
2
+ require 'roda/contrib/action/dispatchable'
3
+
4
+ module RodaContrib
5
+ # The mixin is intended to use with the multi_dispatch plugin. It ships with
6
+ # Dispatchable module by default. Currently, it will load all modules defined
7
+ # under the RodaContrib::Action module
8
+ #
9
+ # If you want to use this mixin seperately, you must define the delegators
10
+ # properly:
11
+ #
12
+ # SomeDispathcer.define_delegators(RodaApp)
13
+ #
14
+ # Examples:
15
+ # see the multi_dispatch plugin
16
+ module Action
17
+ def self.included(base)
18
+ mod = self
19
+
20
+ base.class_eval do
21
+ extend ::Forwardable
22
+
23
+ mod.constants.each do |k|
24
+ c = mod.const_get(k)
25
+ include c if c.is_a? Module
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ module RodaContrib
2
+ module Action
3
+ # Basic functionalities for +RodaContrib::Action+ mixin
4
+ #
5
+ # The call method is already taken by the roda app, so we have to introduce
6
+ # a new method finish to actually executing the route block.
7
+ module Dispatchable
8
+ def self.included(base)
9
+ base.class_eval do
10
+ include InstanceMethods
11
+ extend ClassMethods
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ def initialize(scope)
17
+ @scope = scope
18
+ end
19
+
20
+ attr_reader :scope
21
+
22
+ def finish
23
+ blk = self.class.route_block
24
+ instance_exec(request, &blk)
25
+ end
26
+ end
27
+
28
+ module ClassMethods
29
+ attr_reader :route_block
30
+
31
+ def route(&block)
32
+ @route_block = block
33
+ end
34
+
35
+ def define_delegators(app)
36
+ m = app.instance_methods - Object.instance_methods
37
+ def_delegators :@scope, *m
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,68 @@
1
+ require 'rack/csrf'
2
+
3
+ module RodaContrib
4
+ module Plugins
5
+ # The contrib_csrf plugin is a bit different from offical csrf plugin. It
6
+ # offers only one instance methods instead of five. It is just my personal
7
+ # flavor.
8
+ #
9
+ # You can use it like this:
10
+ # # in the routing tree
11
+ # csrf.field # equivalent to offical csrf_field
12
+ # csrf.header # equivalent to offical csrf_header
13
+ # csrf.metatag({}) # equivalent to offical csrf_metatag({})
14
+ # csrf.tag # equivalent to offical csrf_tag
15
+ # csrf.token # equivalent to offical csrf_token
16
+ #
17
+ # see alse Roda offical csrf plugin documentations
18
+ module Csrf
19
+ CSRF = ::Rack::Csrf
20
+
21
+ def self.configure(app, opts={})
22
+ return if opts[:skip_middleware]
23
+ app.instance_exec do
24
+ @middleware.each do |(mid, *rest), _|
25
+ if mid.equal?(CSRF)
26
+ rest[0].merge!(opts)
27
+ build_rack_app
28
+ return
29
+ end
30
+ end
31
+ use CSRF, opts
32
+ end
33
+ end
34
+
35
+ module InstanceMethods
36
+ class CsrfDecorator
37
+ def initialize(env)
38
+ @env = env
39
+ end
40
+
41
+ def field
42
+ CSRF.field
43
+ end
44
+
45
+ def header
46
+ CSRF.header
47
+ end
48
+
49
+ def metatag(opts={})
50
+ CSRF.metatag(@env, opts)
51
+ end
52
+
53
+ def tag
54
+ CSRF.tag(@env)
55
+ end
56
+
57
+ def token
58
+ CSRF.token(@env)
59
+ end
60
+ end
61
+
62
+ def csrf
63
+ @_csrf ||= CsrfDecorator.new(env)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,42 @@
1
+ module RodaContrib
2
+ module Plugins
3
+ # the load_all plugin helps to write clean code loading related parts of
4
+ # the main roda app.
5
+ #
6
+ # It favors the +:root+ option of the roda app. If you set the +:root+
7
+ # option before you load this plugin, you can omit the +:root+ option of
8
+ # the plugin.
9
+ #
10
+ # Besides, you can load multiple directories at the same time, if loading
11
+ # order does not matter.
12
+ #
13
+ # === Example
14
+ # class App < Roda
15
+ # plugin :contrib_load_all, root: __dir__
16
+ #
17
+ # # load multiple resources at the same time
18
+ # load_all :models, :views
19
+ # # load only one folder
20
+ # load_all :helpers
21
+ # end
22
+ #
23
+ # It will immediately load models and helpers files under the defined root
24
+ # dir.
25
+ module LoadAll
26
+ def self.configure(app, opts={})
27
+ raise ArgumentError, 'Invalid root option' unless app.opts[:root] || opts[:root]
28
+ app.opts[:root] = opts[:root] if opts[:root]
29
+ end
30
+
31
+ module ClassMethods
32
+ def load_all(*rcs)
33
+ rcs.each do |rc|
34
+ patterns = File.expand_path "./#{rc}/**/*.rb", opts[:root]
35
+ Dir[patterns].each { |f| require f }
36
+ end
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,208 @@
1
+ require 'roda/contrib/action'
2
+
3
+ module RodaContrib
4
+ module Plugins
5
+ # The +multi_dispatch+ plugin let you process the your request in a
6
+ # different context rather than the main roda app. It borrows a lot of code
7
+ # from the official +multi_route+ plugin.
8
+ #
9
+ # === Rationals
10
+ # The original rational behind it is simple: avoiding huge interface which
11
+ # is hard to maintain. The reason why this approach is viable is that
12
+ # all routing methods lives within the +Roda::RodaRequest+ class. Thus,
13
+ # wherever you can access the request object, you can route and proceed
14
+ # your request.
15
+ #
16
+ # === Features
17
+ # The +RodaContrib+ ships a mixin to make the plugin work. You can also use
18
+ # this plugin in a more object oriented way.
19
+ #
20
+ # Just like +multi_route+ plugin support namespaced routes, +multi_dispatch+
21
+ # plugin support namespace but a bit differently. Also there can be an
22
+ # extra block pass to the +multi_dispatch+ method to handle requests not
23
+ # handled by dispatchers.
24
+ #
25
+ # === Things you should take care of
26
+ # The +multi_dispatch+ plugin should work fine with most of other plugins.
27
+ # The +render+ plugin is an exception, for it is evaluated in the roda app
28
+ # instance. You should either specify the scope option explicitly or use
29
+ # the +view_options+ plugin to set the scope in the routing tree before you
30
+ # render anything.
31
+ #
32
+ # There is one more thing you should pay attention to. You should always
33
+ # define dispatch after you load all the plugins and the helper mixins into
34
+ # your class.
35
+ #
36
+ # === Example
37
+ # class App < Roda
38
+ # plugin :contrib_multi_dispatch
39
+ #
40
+ # # define dispatchers
41
+ # dispatch 'hello' do
42
+ # def say_hello
43
+ # 'hello'
44
+ # end
45
+ #
46
+ # route do |r|
47
+ # r.get do
48
+ # say_hello
49
+ # end
50
+ # end
51
+ # end
52
+ #
53
+ # dispatch 'hi' do
54
+ # # we can define method with the same name in different dispatchers
55
+ # def say_hello
56
+ # 'said hi instead of hello'
57
+ # end
58
+ #
59
+ # route do |r|
60
+ # r.get do
61
+ # say_hello
62
+ # end
63
+ # end
64
+ # end
65
+ #
66
+ # # namespaced dispatcher
67
+ # dispatch 'yarn', namespace: 'somebody' do
68
+ # def yarn
69
+ # 'somebody yarned'
70
+ # end
71
+ #
72
+ # route do |r|
73
+ # r.get do
74
+ # yarn
75
+ # end
76
+ # end
77
+ # end
78
+ #
79
+ # # class based dispatcher
80
+ # class SayGoodbye
81
+ # include ::RodaContrib::Action
82
+ #
83
+ # def say_good_bye
84
+ # 'goodbye'
85
+ # end
86
+ #
87
+ # route do |r|
88
+ # r.get do
89
+ # say_good_bye
90
+ # end
91
+ # end
92
+ # end
93
+ #
94
+ # dispatch 'goodbye', to: SayGoodbye
95
+ #
96
+ # route do |r|
97
+ # # dispatch request without namespace
98
+ # r.multi_dispatch
99
+ #
100
+ # r.on 'somebody' do
101
+ # # dispatch namespaced dispatchers
102
+ # r.multi_dispatch('somebody')
103
+ # end
104
+ # end
105
+ # end
106
+ #
107
+ # the example above shows you how to add dispatchers, how to use namespaced
108
+ # dispatchers, how to use class based dispatchers, how to dispatch request
109
+ # to dispatchers.
110
+ module MultiDispatch
111
+ def self.configure(app)
112
+ app.opts[:namespaced_dispatchers] ||= {}
113
+ app::RodaRequest.instance_variable_set(:@namespaced_dispatchers_regexps, {})
114
+ app.opts[:namespaced_dispatchers].each do |ns, dispatchers|
115
+ app::RodaRequest.build_named_dispatcher_regexp!(ns)
116
+ end
117
+ end
118
+
119
+ module ClassMethods
120
+ def freeze
121
+ opts[:namespaced_dispatchers].freeze
122
+ opts[:namespaced_dispatchers].each_value(&:freeze)
123
+ super
124
+ end
125
+
126
+ def inherited(subclass)
127
+ super
128
+ sub_ndps = subclass.opts[:namespaced_dispatchers] = {}
129
+ opts[:namespaced_dispatchers].each do |k1, v1|
130
+ sub_ndps[k1] = {}
131
+ v1.each do |k2, v2|
132
+ sub_ndps[k1][k2] = v2.dup
133
+ end
134
+ end
135
+ subclass::RodaRequest.instance_variable_set(:@namespaced_dispatchers_regexps, {})
136
+ sub_ndps.each { |k, v| subclass::RodaRequest.build_named_dispatcher_regexp!(k) }
137
+ end
138
+
139
+ def named_dispathers(namespace=nil)
140
+ targets = opts[:namespaced_dispatchers][namespace]
141
+ targets ? targets.keys : []
142
+ end
143
+
144
+ def named_dispatcher(name, namespace=nil)
145
+ opts[:namespaced_dispatchers][namespace][name]
146
+ end
147
+
148
+ def dispatch(name, namespace: nil, to: nil, &block)
149
+ opts[:namespaced_dispatchers][namespace] ||= {}
150
+
151
+ if dispatcher = opts[:namespaced_dispatchers][namespace][name]
152
+ dispatcher.class_eval(&block)
153
+ elsif to.nil?
154
+ roda_app = self
155
+ dispatcher = Class.new do
156
+ include ::RodaContrib::Action
157
+ define_delegators(roda_app)
158
+ class_eval(&block)
159
+ end
160
+ else
161
+ to.define_delegators(self)
162
+ end
163
+
164
+ opts[:namespaced_dispatchers][namespace][name] = dispatcher || to
165
+ self::RodaRequest.clear_named_dispatcher_regexp!(namespace)
166
+ self::RodaRequest.build_named_dispatcher_regexp!(namespace)
167
+ end
168
+ end
169
+
170
+ module RequestClassMethods
171
+ def clear_named_dispatcher_regexp!(namespace=nil)
172
+ @namespaced_dispatchers_regexps.delete(namespace)
173
+ end
174
+
175
+ def build_named_dispatcher_regexp!(namespace=nil)
176
+ @namespaced_dispatchers_regexps[namespace] = /(#{Regexp.union(dispatcher_ary(namespace))})/
177
+ end
178
+
179
+ def named_dispatcher_regexp(namespace=nil)
180
+ @namespaced_dispatchers_regexps[namespace]
181
+ end
182
+
183
+ private
184
+ def dispatcher_ary(namespace)
185
+ roda_class.named_dispathers(namespace).select{ |s| s.is_a?(String) }.sort.reverse
186
+ end
187
+ end
188
+
189
+ module RequestMethods
190
+ def multi_dispatch(namespace=nil)
191
+ on self.class.named_dispatcher_regexp(namespace) do |section|
192
+ r = dispatch(section, namespace: namespace)
193
+ if block_given?
194
+ yield
195
+ else
196
+ r
197
+ end
198
+ end
199
+ end
200
+
201
+ def dispatch(name, namespace: nil)
202
+ dispatcher = roda_class.named_dispatcher(name, namespace)
203
+ dispatcher.new(scope).finish
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
@@ -1,3 +1,3 @@
1
1
  module RodaContrib
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -0,0 +1,3 @@
1
+ require 'roda/contrib/plugins/csrf'
2
+
3
+ Roda::RodaPlugins.register_plugin(:contrib_csrf, RodaContrib::Plugins::Csrf)
@@ -0,0 +1,3 @@
1
+ require 'roda/contrib/plugins/load_all'
2
+
3
+ Roda::RodaPlugins.register_plugin(:contrib_load_all, RodaContrib::Plugins::LoadAll)
@@ -0,0 +1,3 @@
1
+ require 'roda/contrib/plugins/multi_dispatch'
2
+
3
+ Roda::RodaPlugins.register_plugin(:contrib_multi_dispatch, RodaContrib::Plugins::MultiDispatch)
data/roda-contrib.gemspec CHANGED
@@ -14,8 +14,10 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = 'https://github.com/luciusgone/roda-contrib'
15
15
  spec.license = 'MIT'
16
16
 
17
+ spec.required_ruby_version = ">= 2.3.1"
18
+
17
19
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features|bin)/})
20
+ f.match(%r{^(test|spec|features|bin|www)/})
19
21
  end
20
22
  spec.bindir = 'exe'
21
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -24,4 +26,9 @@ Gem::Specification.new do |spec|
24
26
  spec.add_development_dependency 'bundler', '~> 1.14'
25
27
  spec.add_development_dependency 'rake', '~> 10.0'
26
28
  spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'yard'
30
+ spec.add_development_dependency 'rack-test'
31
+ spec.add_development_dependency 'rack_csrf'
32
+
33
+ spec.add_dependency 'roda', '~> 2.0'
27
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda-contrib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - luciusgone
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-05 00:00:00.000000000 Z
11
+ date: 2017-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,62 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack-test
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack_csrf
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: roda
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
55
111
  description: Small collection of my personal plugins for Roda
56
112
  email:
57
113
  - luciusgone@gmail.com
@@ -62,12 +118,24 @@ files:
62
118
  - ".gitignore"
63
119
  - ".rspec"
64
120
  - ".travis.yml"
121
+ - ".yardopts"
122
+ - CHANGELOG
65
123
  - Gemfile
66
124
  - LICENSE.txt
67
125
  - README.md
68
126
  - Rakefile
127
+ - doc/release_notes/0_1_0.rdoc
128
+ - doc/release_notes/0_2_0.rdoc
69
129
  - lib/roda/contrib.rb
130
+ - lib/roda/contrib/action.rb
131
+ - lib/roda/contrib/action/dispatchable.rb
132
+ - lib/roda/contrib/plugins/csrf.rb
133
+ - lib/roda/contrib/plugins/load_all.rb
134
+ - lib/roda/contrib/plugins/multi_dispatch.rb
70
135
  - lib/roda/contrib/version.rb
136
+ - lib/roda/plugins/contrib_csrf.rb
137
+ - lib/roda/plugins/contrib_load_all.rb
138
+ - lib/roda/plugins/contrib_multi_dispatch.rb
71
139
  - roda-contrib.gemspec
72
140
  homepage: https://github.com/luciusgone/roda-contrib
73
141
  licenses:
@@ -81,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
149
  requirements:
82
150
  - - ">="
83
151
  - !ruby/object:Gem::Version
84
- version: '0'
152
+ version: 2.3.1
85
153
  required_rubygems_version: !ruby/object:Gem::Requirement
86
154
  requirements:
87
155
  - - ">="