ruby-dagger 0.1.1 → 0.2.0

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: d74463b8145c28c660a15879bd8e3ce3ff2059aa7bd9fbf6ec58ed0d2412d7b2
4
- data.tar.gz: ea0364d683460c925dddc028dbbb041e06774cba69c3725d738c9a850bffa5c5
3
+ metadata.gz: 4f9f8d4432457feb3dc6ba9ec83c29f75f2acf0844fd7c9b6ab123d3555f6d91
4
+ data.tar.gz: 2bffbf05b225e888c28f36d3cb25c4277b616d35d6bcdec7bc40c5f7e266fd2e
5
5
  SHA512:
6
- metadata.gz: 9e0e6bde47b0aeed349122b293fcd4322febe07c9a6d85c1e469e479661d4152aa01ed62340dc26d4a901acba5951a0cd4ca53f012da6f06ff30e9d8fddf94a2
7
- data.tar.gz: 20e4b90104dc47c3abe92b9fed52f3a7b4f3fdb101154f62b2bd2cd9a46fb7dc8c6cabb922dc4e0aa0df997c85524c8ea37979a75f1ba9abc74cd92311a0787c
6
+ metadata.gz: b1ec64aeaddec996a0235df76ebc797ab2ec0c04cef3aa1cc4482054a5d7248a4100d8e4420aeecbff6a3a589bf6664d96e75c3e974bc4cd7e14632f9cad49f8
7
+ data.tar.gz: c30423f432e38dd25dbb525c2458b6508b746f4b53057b6ef27b8eca8fe4ca6ee996c2131e3cf1d8f8faa1633fb7f410c71d1366a27a1d13f795fefaf81090dc
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  .rspec_status
12
12
  /vendor
13
13
  /Gemfile.lock
14
+ coverage
@@ -1,3 +1,6 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
1
4
  Metrics/BlockLength:
2
5
  Exclude:
3
6
  - 'spec/*_spec.rb'
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/setup'
2
4
  require 'bundler/gem_tasks'
3
5
 
@@ -11,4 +13,4 @@ desc 'Run RSpec'
11
13
  require 'rspec/core/rake_task'
12
14
  RSpec::Core::RakeTask.new(:spec)
13
15
 
14
- task default: %i[rubocop spec]
16
+ task default: %i[spec rubocop]
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'dagger'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'yaml'
3
5
  require 'dagger/graph'
@@ -5,8 +7,8 @@ require 'dagger/graph'
5
7
  # Manage a DAG, stored in a posix file structure
6
8
  #
7
9
  module Dagger
8
- def self.load(dir)
9
- Graph.load(dir)
10
+ def self.load(dir, **kwargs)
11
+ Graph.load(dir, **kwargs)
10
12
  end
11
13
  end
12
14
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ostruct'
2
4
 
3
5
  module Dagger
@@ -1,20 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
4
+ require 'key_tree/refinements'
2
5
  require_relative 'context'
3
6
  require_relative 'generator'
4
7
 
5
8
  module Dagger
6
9
  # Default value generator for a dictionary
7
10
  class Default
8
- # Initialize a default value generator for a +dictionary+
11
+ using KeyTree::Refinements
12
+
13
+ def self.proc(*args)
14
+ new(*args).default_proc
15
+ end
16
+
17
+ # Initialize a default value generator for a +vertex+
9
18
  #
10
19
  # :call-seq:
11
- # new(dictionary) => Dagger::Default
20
+ # new(graph, vertex) => Dagger::Default
12
21
  # new(*, cached: false)
13
22
  # new(*, rule_prefix: '_default')
14
- def initialize(dictionary, cached: false, rule_prefix: '_default')
15
- @dictionary = dictionary
23
+ def initialize(vertex,
24
+ cached: false,
25
+ fallback: nil,
26
+ rule_prefix: '_default')
27
+ @vertex = vertex
16
28
  @cached = cached
17
- @rule_prefix = KeyTree::Path[rule_prefix]
29
+ @fallback = fallback
30
+ @rule_prefix = rule_prefix.to_key_path
18
31
  @default_proc = ->(tree, key) { generate(tree, key) }
19
32
  @locks = Set[]
20
33
  end
@@ -32,21 +45,41 @@ module Dagger
32
45
 
33
46
  # Generate a default value for a +key+, possibly caching the
34
47
  # result in the +tree+.
35
- # Raises a +KeyError+ f the default value cannot be generated.
36
48
  #
37
49
  # :call-seq:
38
50
  # generate(tree, key) => value || KeyError
51
+ #
52
+ # Raises a +KeyError+ if the default value cannot be generated.
53
+ # Raises a +RuntimeError+ in case of a deadlock for +key+.
39
54
  def generate(tree, key)
40
- key = KeyTree::Path[key] unless key.is_a? KeyTree::Path
41
- raise %(deadlock detected: "#{key}") unless @locks.add?(key)
55
+ key = key.to_key_path
56
+ with_locked_key(key) { |locked_key| cached_value(tree, locked_key) }
57
+ end
42
58
 
43
- return result = process(key) unless cached?
44
- tree[key] = result unless result.nil?
59
+ private
60
+
61
+ # Process a +block+ with mutex for +key+
62
+ #
63
+ # :call-seq:
64
+ # with_locked_key(key &->(locked_key)) => result
65
+ def with_locked_key(key)
66
+ raise %(deadlock detected: "#{key}") unless @locks.add?(key)
67
+ yield(key)
45
68
  ensure
46
69
  @locks.delete(key)
47
70
  end
48
71
 
49
- private
72
+ # Return the default value for +key+, caching it in +tree+ if enabled.
73
+ #
74
+ # :call-seq:
75
+ # cached_value(tree, key) => value || KeyError
76
+ def cached_value(tree, key)
77
+ result = process(key)
78
+ return result unless result.nil?
79
+ result = @fallback&.[](key)
80
+ ensure
81
+ tree[key] = result if cached? && !result.nil?
82
+ end
50
83
 
51
84
  # Process value generation rules for +context+, raising a +KeyError+
52
85
  # if a value could not be generated. Catches :result thows from rule
@@ -56,21 +89,23 @@ module Dagger
56
89
  # yield => value || KeyError
57
90
  def process(key)
58
91
  catch do |ball|
59
- default_rules(key).each do |rule|
60
- context = Context.new(result: ball, dictionary: @dictionary)
61
-
92
+ default_rules(key)&.each do |rule|
93
+ context = Context.new(dictionary: @vertex,
94
+ result: ball,
95
+ vertex: @vertex)
62
96
  process_rule_chain(rule, context)
63
97
  end
64
- raise KeyError, %(no rule succeeded for "#{key}")
98
+ nil
65
99
  end
66
100
  end
67
101
 
68
102
  # Return the default value generation rules for a +key+.
69
103
  #
70
104
  # :call-seq:
71
- # default_rules(key) => Array of Hash || KeyError
105
+ # default_rules(key) => Array of Hash
72
106
  def default_rules(key)
73
- @dictionary.fetch(@rule_prefix + key)
107
+ result = @vertex.fetch(@rule_prefix + key, nil)
108
+ result
74
109
  end
75
110
 
76
111
  # Process the methods in a rule chain
@@ -78,12 +113,13 @@ module Dagger
78
113
  # :call-seq:
79
114
  # process_rule_chain(rule_chain, context)
80
115
  def process_rule_chain(rule_chain, context)
81
- rule_chain.each do |key, arg|
82
- klass = Dagger::Generate.const_get(camelize(key))
83
- klass[context, arg, &->(value) { throw context.result, value }]
116
+ catch do |ball|
117
+ context.stop = ball
118
+ rule_chain.each do |key, arg|
119
+ klass = Dagger::Generate.const_get(camelize(key))
120
+ klass[context, arg, &->(value) { throw context.result, value }]
121
+ end
84
122
  end
85
- rescue StopIteration
86
- nil
87
123
  end
88
124
 
89
125
  # Convert snake_case to CamelCase
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module Dagger
@@ -40,16 +42,14 @@ module Dagger
40
42
 
41
43
  private
42
44
 
43
- delegate %i[dictionary] => :@context
45
+ delegate %i[dictionary vertex] => :@context
44
46
 
45
47
  # Stop processing the current rule chain
46
48
  #
47
49
  # :call-seq:
48
50
  # stop
49
- #
50
- # Raises +StopIteration+
51
51
  def stop
52
- raise StopIteration
52
+ throw @context.stop
53
53
  end
54
54
 
55
55
  # Update context attributes with new values
@@ -67,6 +67,20 @@ module Dagger
67
67
  def enumerable(value)
68
68
  value.respond_to?(:each) ? value : [value]
69
69
  end
70
+
71
+ # Format a +string+ with values from a +dictionary+
72
+ #
73
+ # :call-seq:
74
+ # format(string)
75
+ def format_string(string)
76
+ hash = Hash.new do |_, key|
77
+ result = @context.dictionary[key]
78
+ next result unless result.nil?
79
+ return nil
80
+ end
81
+
82
+ format(string, hash)
83
+ end
70
84
  end
71
85
  end
72
86
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../generator'
2
4
 
3
5
  module Dagger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../generator'
2
4
 
3
5
  module Dagger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../generator'
2
4
 
3
5
  module Dagger
@@ -9,9 +11,8 @@ module Dagger
9
11
  # - ...
10
12
  class RequireName < Dagger::Generator
11
13
  def process(regexps)
12
- string = dictionary['_meta.name']
13
14
  stop unless enumerable(regexps).any? do |regexp|
14
- ::Regexp.new(regexp).match?(string)
15
+ ::Regexp.new(regexp).match?(vertex.name)
15
16
  end
16
17
  end
17
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../generator'
2
4
 
3
5
  module Dagger
@@ -12,22 +14,10 @@ module Dagger
12
14
  class String < Dagger::Generator
13
15
  def process(strings)
14
16
  enumerable(strings).each do |fmtstr|
15
- result = format_string(fmtstr, dictionary)
17
+ result = format_string(fmtstr)
16
18
  yield result unless result.nil?
17
19
  end
18
20
  end
19
-
20
- private
21
-
22
- # Format a +string+ with values from a +dictionary+
23
- #
24
- # :call-seq:
25
- # format_string(string, dictionary)
26
- def format_string(string, dictionary)
27
- Kernel.format(string, Hash.new { |_, key| dictionary[key] })
28
- rescue KeyError
29
- nil
30
- end
31
21
  end
32
22
  end
33
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tangle'
2
4
  require 'tangle/mixin/directory'
3
5
  require_relative 'vertex'
@@ -5,17 +7,16 @@ require_relative 'vertex'
5
7
  module Dagger
6
8
  # Specialization of Tangle::DAG
7
9
  class Graph < Tangle::DAG
8
- DEFAULT_MIXINS = [Tangle::Mixin::Directory].freeze
9
-
10
- def self.load(dir)
10
+ def self.load(dir, cached: false)
11
+ @cached = cached
11
12
  dir_options = {
12
13
  root: File.realpath(dir),
13
14
  loaders: %i[symlink_loader directory_loader keytree_loader]
14
15
  }
15
- new(directory: dir_options)
16
+ new(directory: dir_options, currify: true)
16
17
  end
17
18
 
18
- def initialize(*)
19
+ def initialize(mixins: [Tangle::Mixin::Directory], **)
19
20
  @deferred_edges = []
20
21
  super
21
22
  @deferred_edges.each do |args|
@@ -28,6 +29,10 @@ module Dagger
28
29
  vertices.select { |vertex| yield(self, vertex) }
29
30
  end
30
31
 
32
+ def cached?
33
+ !(!@cached)
34
+ end
35
+
31
36
  protected
32
37
 
33
38
  def symlink_loader(path:, parent:, lstat:, **)
@@ -42,7 +47,7 @@ module Dagger
42
47
  return unless lstat.directory?
43
48
 
44
49
  path = local_path(path)
45
- vertex = Vertex.new(path)
50
+ vertex = Vertex.new(path, cached: cached?)
46
51
  add_vertex(vertex)
47
52
  return true if parent.nil?
48
53
  parent = local_path(parent)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dagger # rubocop:disable Style/Documentation
4
+ begin
5
+ require 'git-version-bump'
6
+ VERSION = GVB.version.freeze
7
+ rescue LoadError
8
+ VERSION = '0.0.0.UNDEF'
9
+ end
10
+ end
@@ -1,59 +1,119 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'key_tree'
4
+ require 'key_tree/refinements'
2
5
  require_relative 'default'
3
6
 
4
7
  module Dagger
5
8
  # Vertex class for Dagger, representing a filesystem directory
9
+ #
10
+ # dir/
11
+ # file.yaml => keytree
12
+ # prefix@file.yaml => prefix.keytree
13
+ #
14
+ # +forest+ = [ +meta+ = {},
15
+ # +local+ [ { file_keys }, ... ],
16
+ # [ { Default } ],
17
+ # +inherited+ = [ [ parent ], ... ]
18
+ # ]
19
+ #
6
20
  class Vertex
7
- def initialize(name)
8
- initialize_forest
21
+ using KeyTree::Refinements
9
22
 
10
- meta['_meta.name'] = name
11
- meta['_meta.basename'] = File.basename(name)
12
- meta['_meta.dirname'] = File.dirname(name)
23
+ def initialize(name, cached: false)
24
+ @forest = initialize_forest(cached)
25
+ @meta['_meta.name'] = name
26
+ @meta['_meta.basename'] = File.basename(name)
27
+ @meta['_meta.dirname'] = File.dirname(name)
13
28
  end
14
29
 
15
- attr_reader :inherited, :keys, :local, :meta
30
+ def to_key_forest
31
+ @forest
32
+ end
33
+ alias to_key_wood to_key_forest
16
34
 
17
35
  def name
18
- meta['_meta.name']
36
+ @forest['_meta.name']
19
37
  end
38
+ alias to_s name
20
39
 
21
40
  def [](key)
22
- key = KeyTree::Path[key] unless key.is_a? KeyTree::Path
23
- return inherited[key[1..-1]] if key.prefix?(KeyTree::Path['^'])
24
- keys[key]
41
+ key = key.to_key_path
42
+ @inherited[key.drop(1)] if key.prefix?('^')
43
+ @forest[key]
25
44
  end
26
45
 
27
- def fetch(key)
28
- keys.fetch(key)
46
+ def fetch(key, *default, &block)
47
+ key = key.to_key_path
48
+ @inherited.fetch(key.drop(1), *default, &block) if key.prefix?('^')
49
+ @forest.fetch(key, *default, &block)
29
50
  end
30
51
 
31
52
  def <<(keytree)
32
- local << keytree
53
+ @local << keytree
33
54
  end
34
55
 
35
56
  def edge_added(edge)
36
57
  return unless edge.head?(self)
37
- inherited << edge.tail.keys
58
+ @inherited << edge.tail.to_key_wood
38
59
  end
39
60
 
40
61
  def edge_removed(edge)
41
62
  return unless edge.head?(self)
42
- inherited.reject! { |tree| tree.equal?(edge.tail.keys) }
63
+ @inherited.reject! { |tree| tree.equal?(edge.tail.to_key_wood) }
43
64
  end
44
65
 
45
- alias to_s name
66
+ def added_to_graph(graph)
67
+ raise %(belongs another graph) if @graph&.!= graph
68
+ @graph = graph
69
+ end
70
+
71
+ def removed_from_graph(graph)
72
+ raise %(not part of graph) if @graph&.!= graph
73
+ @graph = nil
74
+ end
75
+
76
+ def flatten(cleanup: true)
77
+ forest = initialize_forest(true)
78
+
79
+ forest.key_paths.select { |key| key.prefix?('_default') }.each do |key|
80
+ forest[key.drop(1)]
81
+ end
82
+
83
+ flattened = forest.flatten
84
+ return flattened unless cleanup
85
+ flattened.to_h.delete_if { |key| key.to_s.start_with?('_') }
86
+ flattened
87
+ end
88
+
89
+ def to_h
90
+ flatten(cleanup: true).to_h
91
+ end
92
+
93
+ def to_yaml
94
+ flatten(cleanup: true).to_yaml
95
+ end
96
+
97
+ def to_json
98
+ flatten(cleanup: true).to_json
99
+ end
46
100
 
47
101
  private
48
102
 
49
- def initialize_forest
50
- @keys = KeyTree::Forest.new
51
- @keys << @meta = KeyTree::Tree.new
52
- @keys << @local = KeyTree::Forest.new
53
- @keys << @default = KeyTree::Forest.new
54
- @keys << @inherited = KeyTree::Forest.new
55
- default_proc = Default.new(self).default_proc
56
- @default << KeyTree::Tree.new(&default_proc)
103
+ def initialize_forest(cached)
104
+ forest = KeyTree::Forest.new
105
+ forest << @meta ||= KeyTree::Tree.new
106
+ forest << @local ||= KeyTree::Forest.new
107
+ forest << default = KeyTree::Forest.new
108
+ forest << @inherited ||= KeyTree::Forest.new
109
+ default << initialize_default_tree(cached)
110
+ forest
111
+ end
112
+
113
+ def initialize_default_tree(cached)
114
+ default_args = cached ? { cached: true, fallback: @inherited } : {}
115
+ default_proc = Default.proc(self, default_args)
116
+ KeyTree::Tree.new(&default_proc)
57
117
  end
58
118
  end
59
119
  end
@@ -1,17 +1,13 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
5
- begin
6
- require 'git-version-bump'
7
- GIT_VERSION = GVB.version.freeze
8
- rescue LoadError
9
- GIT_VERSION = '0.0.0.UNDEF'.freeze
10
- end
6
+ require 'dagger/version'
11
7
 
12
8
  Gem::Specification.new do |spec|
13
9
  spec.name = 'ruby-dagger'
14
- spec.version = GIT_VERSION
10
+ spec.version = Dagger::VERSION
15
11
  spec.authors = ['Calle Englund']
16
12
  spec.email = ['calle@discord.bofh.se']
17
13
 
@@ -27,14 +23,16 @@ Gem::Specification.new do |spec|
27
23
  spec.require_paths = ['lib']
28
24
 
29
25
  spec.platform = Gem::Platform::RUBY
30
- spec.required_ruby_version = '~> 2.1'
26
+ spec.required_ruby_version = '~> 2.3'
31
27
 
32
- spec.add_dependency 'key_tree', '~> 0.5'
33
- spec.add_dependency 'tangle', '~> 0.9'
28
+ spec.add_dependency 'key_tree', '~> 0.6'
29
+ spec.add_dependency 'tangle', '~> 0.10'
34
30
 
35
31
  spec.add_development_dependency 'bundler', '~> 1.16'
36
32
  spec.add_development_dependency 'git-version-bump', '~> 0.15'
37
33
  spec.add_development_dependency 'rake', '~> 10.0'
38
34
  spec.add_development_dependency 'rspec', '~> 3.0'
39
35
  spec.add_development_dependency 'rubocop', '~> 0.52'
36
+ spec.add_development_dependency 'ruby-prof', '~> 0.17'
37
+ spec.add_development_dependency 'simplecov', '~> 0.16'
40
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-dagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Calle Englund
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-26 00:00:00.000000000 Z
11
+ date: 2018-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: key_tree
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.5'
19
+ version: '0.6'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.5'
26
+ version: '0.6'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: tangle
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.9'
33
+ version: '0.10'
34
34
  type: :runtime
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: '0.9'
40
+ version: '0.10'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,34 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.52'
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby-prof
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.17'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.17'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.16'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.16'
111
139
  description:
112
140
  email:
113
141
  - calle@discord.bofh.se
@@ -135,6 +163,7 @@ files:
135
163
  - lib/dagger/generator/require_name.rb
136
164
  - lib/dagger/generator/string.rb
137
165
  - lib/dagger/graph.rb
166
+ - lib/dagger/version.rb
138
167
  - lib/dagger/vertex.rb
139
168
  - ruby-dagger.gemspec
140
169
  homepage: https://github.com/notcalle/ruby-dagger
@@ -149,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
178
  requirements:
150
179
  - - "~>"
151
180
  - !ruby/object:Gem::Version
152
- version: '2.1'
181
+ version: '2.3'
153
182
  required_rubygems_version: !ruby/object:Gem::Requirement
154
183
  requirements:
155
184
  - - ">="