xf 0.0.3 → 0.1.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: ca75c5042852e2391ad547df17f005f23987bfd780512d5d4e3d3f9d963bf972
4
- data.tar.gz: 28cf81f1673af0b96ba1d2e469a181c68539105a45cdaf99970716290c62f22d
3
+ metadata.gz: 62d3af5779614c09634b6f1e53a0507832f1cddc051693f8ccda36fd29cf1862
4
+ data.tar.gz: 357c3a4807a9e5edb5d82c02ed06be8acd25d7e8e5e3224caeb8d67c2a4ad27d
5
5
  SHA512:
6
- metadata.gz: 851f5270c4cd9815bfdf96b0c56ef338b21f0e176990a8e67f3a63c1f50f63d71571c1bb2270bddb3c989a4f48985f968f102e80819b25a7de5d31844afc34ed
7
- data.tar.gz: d00cab86f2bd53031e2d7e19cdb0b7eac9185519430a0e600abeb6e021b9a721cf7a777c868122716ebe6397caf2f8d374bb19c0770b593bd02f00f4cee57ebc
6
+ metadata.gz: c76a5dea28717e733bb1938000fe5efaff5ceb8178f6b46b66d86916bcc1217274cafc05cd6bca3cc0f1986b60f1f93524c18dee29748ad8deea1c74a22ebe35
7
+ data.tar.gz: 44657cd1c09fbd8e624ebcaf807dfc1c705b4434d8bc51084ff735a59b677eb7cc5785188fa7788b6d5d79f7673a3e3b75151b2334cabf765825c954dc89426c
data/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/xf.svg)](http://badge.fury.io/rb/xf)
4
4
  <!-- Replace <id> with Code Climate repository ID. Remove this comment afterwards. -->
5
- [![Code Climate Maintainability](https://api.codeclimate.com/v1/badges/<id>/maintainability)](https://codeclimate.com/github//xf/maintainability)
6
- [![Code Climate Test Coverage](https://api.codeclimate.com/v1/badges/<id>/test_coverage)](https://codeclimate.com/github//xf/test_coverage)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/905faea654f9e0a1f811/maintainability)](https://codeclimate.com/github/baweaver/xf/maintainability)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/905faea654f9e0a1f811/test_coverage)](https://codeclimate.com/github/baweaver/xf/test_coverage)
7
+ [![Build Status](https://travis-ci.org/baweaver/xf.svg?branch=master)](https://travis-ci.org/baweaver/xf)
7
8
 
8
9
  <!-- Tocer[start]: Auto-generated, don't remove. -->
9
10
 
@@ -26,10 +27,14 @@
26
27
 
27
28
  ## Features
28
29
 
29
- **Compose**
30
+ **Compose and Pipe**
30
31
 
31
32
  ```ruby
32
- %w(1 2 3 4).map(&Xf.compose(:to_i, :succ))
33
+ # Read left to right
34
+ %w(1 2 3 4).map(&Xf.pipe(:to_i, :succ))
35
+
36
+ # Read right to left
37
+ %w(1 2 3 4).map(&Xf.compose(:succ, :to_i))
33
38
  ```
34
39
 
35
40
  If it looks like a Proc, or can be convinced to become one, it will work there.
@@ -55,9 +60,9 @@ Let's try setting a value:
55
60
  ```ruby
56
61
  people = [{name: "Robert", age: 22}, {name: "Roberta", age: 22}, {name: "Foo", age: 42}, {name: "Bar", age: 18}]
57
62
 
58
- older_people = people.map(&Xf.scope(:age) { |age| age + 1 })
63
+ age_scope = Xf.scope(:age)
59
64
 
60
- older_people = people.map(&Xf.scope(:age).set { |age| age + 1 })
65
+ older_people = people.map(&age_scope.set { |age| age + 1 })
61
66
  # => [{:name=>"Robert", :age=>23}, {:name=>"Roberta", :age=>23}, {:name=>"Foo", :age=>43}, {:name=>"Bar", :age=>19}]
62
67
 
63
68
  people
@@ -65,7 +70,7 @@ people
65
70
 
66
71
  # set! will mutate, for those tough ground in issues:
67
72
 
68
- older_people = people.map(&Xf.scope(:age).set! { |age| age + 1 })
73
+ older_people = people.map(&age_scope.set! { |age| age + 1 })
69
74
  # => [{:name=>"Robert", :age=>23}, {:name=>"Roberta", :age=>23}, {:name=>"Foo", :age=>43}, {:name=>"Bar", :age=>19}]
70
75
 
71
76
  people
@@ -75,20 +80,59 @@ people
75
80
  It works much the same as `Hash#dig` in that you can pass multiple comma-seperated values as a deeper path:
76
81
 
77
82
  ```
78
- Xf.scope(:children, 0, :name).get.call({name: 'Foo', children: [{name: 'Bar'}]})
83
+ first_child_scope = Xf.scope(:children, 0, :name)
84
+ first_child_scope.get.call({name: 'Foo', children: [{name: 'Bar'}]})
79
85
  # => "Bar"
80
86
 
81
- Xf.scope(:children, 0, :name).set('Baz').call({name: 'Foo', children: [{name: 'Bar'}]})
87
+ first_child_scope.set('Baz').call({name: 'Foo', children: [{name: 'Bar'}]})
82
88
  # => {:name=>"Foo", :children=>[{:name=>"Baz"}]}
83
89
  ```
84
90
 
85
91
  That means array indexes work too, and on both `get` and `set` methods!
86
92
 
93
+ **Traces**
94
+
95
+ A Trace is a lot like a scope, except it'll keep digging until it finds a
96
+ matching value. It takes a single path instead of a set like Scope. Currently
97
+ there are three types:
98
+
99
+ * `Trace` - Match on key
100
+ * `TraceValue` - Match on value
101
+ * `TraceKeyValue` - Match on both key and value
102
+
103
+ Tracers all implement `===` for matchers, which makes them more flexible but also
104
+ a good deal slower than Scopes. Keep that in mind.
105
+
106
+ Let's take a look at a few options real quick. We'll be sampling some data from
107
+ `people.json`, which is generated from [JSON Generator](https://next.json-generator.com/).
108
+
109
+ ```ruby
110
+ require 'json'
111
+ people = JSON.parse(File.read('people.json'))
112
+
113
+ first_name_trace = Xf.trace('first')
114
+
115
+ # Remember it gets _all_ matching values, resulting in a nested array. Use
116
+ # `flat_map` if you want a straight list.
117
+ people.map(&first_name_trace.get)
118
+ # => [["Erickson"], ["Pugh"], ["Mullen"], ["Jacquelyn"], ["Miller"], ["Jolene"]]
119
+
120
+ # You can even compose them if you want to. Just remember compose
121
+ people.flat_map(&Xf.compose(first_name_trace.set('Spartacus'), first_name_trace.get))
122
+ # => ["Spartacus", "Spartacus", "Spartacus", "Spartacus", "Spartacus", "Spartacus"]
123
+ ```
124
+
125
+ Depending on requests, I may make a NarrowScope that only returns the first match
126
+ instead of digging the entire hash. At the moment most of my usecases involve
127
+ data that's not so kind as to give me that option.
128
+
87
129
  ## Screencasts
88
130
 
89
131
  ## Requirements
90
132
 
91
- 0. [Ruby 2.5.1](https://www.ruby-lang.org)
133
+ 0. [Ruby 2.3.x](https://www.ruby-lang.org)
134
+
135
+ > **Note**: For development you'll want to be using 2.5.0+ for various rake tasks and other niceties.
92
136
 
93
137
  ## Setup
94
138
 
@@ -12,7 +12,7 @@ module Xf
12
12
  end
13
13
 
14
14
  def self.version
15
- "0.0.3"
15
+ "0.1.0"
16
16
  end
17
17
 
18
18
  def self.version_label
@@ -1,25 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'xf/scope'
4
+ require 'xf/trace'
5
+ require 'xf/trace_value'
6
+ require 'xf/trace_key_value'
4
7
 
5
8
  module Xf
6
9
  module PublicApi
7
- # Composes a list of functions, or items that respond to `to_proc`, into
10
+ # Combines a list of functions, or items that respond to `to_proc`, into
8
11
  # a function chain that can be called against a target.
9
12
  #
13
+ # @note
14
+ # This _could_ be done with reduce, but we're trying to keep performance
15
+ # as close to vanilla as possible.
16
+ #
10
17
  # @param *fns [#to_proc] List of objects coercible into Procs
11
18
  #
12
19
  # @return [Proc[Any] -> Any]
13
- def compose(*fns)
14
- chain = fns.map(&:to_proc)
15
-
20
+ def pipe(*fns)
16
21
  Proc.new { |target|
17
- chain.reduce(target) { |t, fn| fn.call(t) }
22
+ new_value = target
23
+ fns.each { |fn| new_value = fn.to_proc.call(new_value) }
24
+ new_value
18
25
  }
19
26
  end
20
27
 
28
+ alias_method :p, :pipe
29
+
30
+ # The more traditional functional Compose, where things go in the opposite
31
+ # order. Pipe is probably more intuitive to Rubyists, which is why this
32
+ # is an implementation of pipe.
33
+ #
34
+ # @see #pipe
35
+ def compose(*fns)
36
+ pipe(*fns.reverse)
37
+ end
38
+
21
39
  alias_method :c, :compose
22
40
 
41
+
23
42
  # Creates a Scope.
24
43
  #
25
44
  # @see Xf::Scope
@@ -28,13 +47,98 @@ module Xf
28
47
  # See the README for more instructions on usage. Will likely propogate
29
48
  # more examples here and into the specs later.
30
49
  #
31
- # @param *path [Array[Any]] Hash#dig accessible segments
50
+ # @param *paths [Array[Any]] Hash#dig accessible segments
32
51
  #
33
52
  # @return [Xf::Scope]
34
- def scope(*path)
35
- Scope.new(path)
53
+ def scope(*paths)
54
+ Scope.new(paths.flatten)
36
55
  end
37
56
 
38
57
  alias_method :s, :scope
58
+
59
+ # Creates a Trace.
60
+ #
61
+ # @see Xf::Trace
62
+ #
63
+ # @param trace_path [Any]
64
+ # Any hash key to dive searching for.
65
+ #
66
+ # @return [Xf::Trace]
67
+ def trace(trace_path)
68
+ Trace.new(trace_path)
69
+ end
70
+
71
+ alias_method :t, :trace
72
+
73
+ # Creates a TraceValue, which matches against a value rather than a key.
74
+ #
75
+ # @see Xf::TraceValue
76
+ #
77
+ # @param trace_path [Any]
78
+ # Any hash value to dive searching for
79
+ #
80
+ # @return [Xf::TraceValue]
81
+ def trace_value(trace_path)
82
+ TraceValue.new(trace_path)
83
+ end
84
+
85
+ alias_method :tv, :trace_value
86
+
87
+ # Creates a TraceKeyValue, which matches against a value rather than a key.
88
+ #
89
+ # @see Xf::TraceKeyValue
90
+ #
91
+ # @param trace_path [Any]
92
+ # Any hash value to dive searching for
93
+ #
94
+ # @return [Xf::TraceValue]
95
+ def trace_key_value(trace_key, trace_value)
96
+ TraceKeyValue.new(trace_key, trace_value)
97
+ end
98
+
99
+ alias_method :tkv, :trace_key_value
100
+
101
+ # Clamps a value to be within a range. Works with numbers, dates, and other
102
+ # items. More of a utility function.
103
+ #
104
+ # @param start_range [Any]
105
+ # Start of a range
106
+ #
107
+ # @param end_range [Any]
108
+ # End of a range
109
+ #
110
+ # @return [Proc[Any] -> Any]
111
+ # Proc that returns a value that's been clamped to the given range
112
+ def clamp(start_range, end_range)
113
+ Proc.new { |target|
114
+ next start_range if target < start_range
115
+ next end_range if target > end_range
116
+
117
+ target
118
+ }
119
+ end
120
+
121
+ # Counts by a function. This is entirely because I hackney this everywhere in
122
+ # pry anyways, so I want a function to do it for me already.
123
+ #
124
+ # @param targets [Array[Any]] Targets to count
125
+ # @param &fn [Proc] Function to define count key
126
+ #
127
+ # @return [Hash[Any, Integer]] Counts
128
+ def count_by(targets, &fn)
129
+ fn ||= -> v { v }
130
+
131
+ targets.each_with_object(Hash.new(0)) { |target, counts|
132
+ counts[fn[target]] += 1
133
+ }
134
+ end
135
+
136
+ # Solely meant as a tap addendum
137
+ #
138
+ # @return [Proc[Any] -> nil]
139
+ # nil from puts result
140
+ def log
141
+ Proc.new { |target| puts target }
142
+ end
39
143
  end
40
144
  end
@@ -48,32 +48,56 @@ module Xf
48
48
  Proc.new { |hash| set_value!(hash, value, &fn) }
49
49
  end
50
50
 
51
- # Private API - Methods below here are subject to change, please don't use
52
- # them directly.
53
-
54
- private def get_value(hash)
51
+ # Direct value getter, though it may be wiser to use Hash#dig here
52
+ # instead if you're concerned about speed.
53
+ #
54
+ # @param hash [Hash] Hash to get value from
55
+ #
56
+ # @return [Any]
57
+ def get_value(hash)
55
58
  hash.dig(*@paths)
56
59
  end
57
60
 
58
- private def set_value(hash, value = nil, &fn)
61
+ # Sets a value at the bottom of a path without mutating the original.
62
+ #
63
+ # @param hash [Hash]
64
+ # Hash to set value on
65
+ #
66
+ # @param value = nil [Any]
67
+ # Value to set
68
+ #
69
+ # @param &fn [Proc]
70
+ # If present, current value is yielded to it and the return
71
+ # value is the new set value
72
+ #
73
+ # @return [Hash]
74
+ # Clone of the original with the value set
75
+ def set_value(hash, value = nil, &fn)
59
76
  set_value!(deep_clone(hash), value, &fn)
60
77
  end
61
78
 
62
- private def set_value!(hash, value = nil, &fn)
79
+ # Mutating form of `#set_value`
80
+ #
81
+ # @see set_value
82
+ def set_value!(hash, value = nil, &fn)
63
83
  lead_in = @paths[0..-2]
64
84
  target_key = @paths[-1]
65
85
 
66
- dive = lead_in.reduce(hash) { |h, s| h[s] }
86
+ new_hash = hash
87
+ lead_in.each { |s| new_hash = new_hash[s] }
67
88
 
68
89
  new_value = block_given? ?
69
- yield(dive[target_key]) :
90
+ yield(new_hash[target_key]) :
70
91
  value
71
92
 
72
- dive[target_key] = new_value
93
+ new_hash[target_key] = new_value
73
94
 
74
95
  hash
75
96
  end
76
97
 
98
+ # Private API - Methods below here are subject to change, please don't use
99
+ # them directly.
100
+
77
101
  private def deep_clone(hash)
78
102
  Marshal.load(Marshal.dump(hash))
79
103
  end
@@ -0,0 +1,108 @@
1
+ module Xf
2
+ # A more abstract version of a Scope in which the lead key is treated as
3
+ # if it could be anywhere in a hash tree. A Trace will dive until it
4
+ # finds _all_ matching nodes.
5
+ #
6
+ # Note that this can potentially be slow, but is also very difficult to emulate
7
+ # succinctly inline in vanilla Ruby.
8
+ #
9
+ # @author baweaver
10
+ # @since 0.1.0
11
+ #
12
+ class Trace
13
+ # Creates a Scope
14
+ #
15
+ # @param trace_path [Any]
16
+ # What node to try and locate
17
+ #
18
+ # @return [Xf::Trace]
19
+ def initialize(trace_path)
20
+ @trace_path = trace_path
21
+ end
22
+
23
+ def get
24
+ Proc.new { |target| get_value(target) }
25
+ end
26
+
27
+ def get_value(hash)
28
+ retrieved_values = []
29
+
30
+ recursing_dive(hash) { |h, k, v| retrieved_values.push(v) }
31
+
32
+ retrieved_values
33
+ end
34
+
35
+ # Sets a value in a Hash
36
+ #
37
+ # @param value = nil [Any]
38
+ # Value to set at the target
39
+ #
40
+ # @param &fn [Proc]
41
+ # Block to yield target value to. Returned value will be set as the new
42
+ # value at the target.
43
+ #
44
+ # @return [Proc[Hash] -> Hash]
45
+ # New Hash with transformation applied
46
+ def set(value = nil, &fn)
47
+ Proc.new { |hash| set_value(hash, value, &fn) }
48
+ end
49
+
50
+ # Mutates a value in a Hash
51
+ #
52
+ # @see #set
53
+ #
54
+ # @note
55
+ # This method does the same thing as `#set`, except that it mutates the
56
+ # target value instead of creating a clone first.
57
+ #
58
+ def set!(value = nil, &fn)
59
+ Proc.new { |hash| set_value!(hash, value, &fn) }
60
+ end
61
+
62
+ def set_value(hash, value = nil, &fn)
63
+ set_value!(deep_clone(hash), value, &fn)
64
+ end
65
+
66
+ def set_value!(hash, value = nil, &fn)
67
+ recursing_dive(hash) { |h, k, v|
68
+ h[k] = block_given? ? yield(v) : value
69
+ }
70
+
71
+ hash
72
+ end
73
+
74
+ # Private API - Methods below here are subject to change, please don't use
75
+ # them directly.
76
+
77
+ # Match is defined as having complete access to a hash, key, and value
78
+ # to make it easier to override for other future fun tasks.
79
+ #
80
+ # In the base case of trace we only _really_ care about the key matching
81
+ # for speed reasons. If you really want power though you could rig this
82
+ # up to work with Qo to query things.
83
+ #
84
+ # @param hash [Hash] [description]
85
+ # @param key [Any] [description]
86
+ # @param value [Any] [description]
87
+ # @param matcher [#===] [description]
88
+ #
89
+ # @return [type] [description]
90
+ private def match?(hash, key, value, matcher)
91
+ matcher === key
92
+ end
93
+
94
+ private def deep_clone(hash)
95
+ Marshal.load(Marshal.dump(hash))
96
+ end
97
+
98
+ private def recursing_dive(target_hash, &fn)
99
+ target_hash.each { |k, v|
100
+ yield(target_hash, k, v) if match?(target_hash, k, v, @trace_path)
101
+
102
+ next unless target_hash[k].is_a?(Hash)
103
+
104
+ recursing_dive(target_hash[k], &fn)
105
+ }
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ module Xf
2
+ # Traces based on a key and a value matching. Only overrides the `match?`
3
+ # method to redefine a matched node.
4
+ #
5
+ # @author baweaver
6
+ # @since 0.1.0
7
+ #
8
+ class TraceKeyValue < Trace
9
+ def initialize(trace_key, trace_value)
10
+ @trace_key = trace_key
11
+ @trace_value = trace_value
12
+ end
13
+
14
+ # Private API - Methods below here are subject to change, please don't use
15
+ # them directly.
16
+
17
+ # @see Trace#match?
18
+ private def match?(hash, key, value, matcher)
19
+ @trace_key === key && @trace_value === value
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module Xf
2
+ # Traces based on a value matching. Only overrides the `match?`
3
+ # method to redefine a matched node.
4
+ #
5
+ # @see Xf::Trace
6
+ #
7
+ # @author baweaver
8
+ # @since 0.1.0
9
+ #
10
+ class TraceValue < Trace
11
+ # Private API - Methods below here are subject to change, please don't use
12
+ # them directly.
13
+
14
+ # @see Trace#match?
15
+ private def match?(hash, key, value, matcher)
16
+ matcher === value
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Weaver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-21 00:00:00.000000000 Z
11
+ date: 2018-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler-audit
14
+ name: gemsmith
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.6'
19
+ version: '12.0'
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
- version: '0.6'
26
+ version: '12.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: codeclimate-test-reporter
28
+ name: git-cop
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.0'
33
+ version: '2.2'
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.0'
40
+ version: '2.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: gemsmith
42
+ name: bundler-audit
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '12.0'
47
+ version: '0.6'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '12.0'
54
+ version: '0.6'
55
55
  - !ruby/object:Gem::Dependency
56
- name: git-cop
56
+ name: codeclimate-test-reporter
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '2.2'
61
+ version: '1.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: '2.2'
68
+ version: '1.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard-rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,34 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0.54'
167
+ - !ruby/object:Gem::Dependency
168
+ name: benchmark-ips
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: qo
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '0.2'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '0.2'
167
195
  description:
168
196
  email:
169
197
  - keystonelemur@gmail.com
@@ -179,6 +207,9 @@ files:
179
207
  - lib/xf/identity.rb
180
208
  - lib/xf/public_api.rb
181
209
  - lib/xf/scope.rb
210
+ - lib/xf/trace.rb
211
+ - lib/xf/trace_key_value.rb
212
+ - lib/xf/trace_value.rb
182
213
  homepage: https://www.github.com/baweaver/xf
183
214
  licenses:
184
215
  - MIT
@@ -192,9 +223,9 @@ require_paths:
192
223
  - lib
193
224
  required_ruby_version: !ruby/object:Gem::Requirement
194
225
  requirements:
195
- - - "~>"
226
+ - - ">="
196
227
  - !ruby/object:Gem::Version
197
- version: '2.5'
228
+ version: '0'
198
229
  required_rubygems_version: !ruby/object:Gem::Requirement
199
230
  requirements:
200
231
  - - ">="