dumb_delimited 1.1.0 → 2.0.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
  SHA256:
3
- metadata.gz: 2a4d7deecbbed56e6940058fdc548436cbdb0f081b43164bc841017601c27726
4
- data.tar.gz: b94ae4701ae2dec7cee54befe2e85c11ea20a9ae5906d0f7da6a8da1ef377eb6
3
+ metadata.gz: '049c4e61de54be67ca44c3b01d7f97fd5f1972953415ed339a14c55ec0c6d0c4'
4
+ data.tar.gz: 38f8e15d6a44ab8af339cf4da8e8addb232c8118ba1b8603e31deb934ca95989
5
5
  SHA512:
6
- metadata.gz: 9f2994715b89523b10c4fb1375b2a073e306cedfae565f502241a4ad8f82876b1ec02d1b453641842ca331bba2812ea73783c70af7cc1431b0bbaeec83e0ce09
7
- data.tar.gz: 36b9db417ddd340f695e1332ea005ad8ec03c3e8d31f5cc395b8479463497bee0e518e89f5916a90d0267ebfe9779abb21995d35e66f8da67b91f282e955b2b1
6
+ metadata.gz: 47aea2da44d901f3606f9e997f6024dd0413f131bec2f7f53db73863c7975a4102996f45a6eef2ffecdbf97d12c2b27132b9689dbb51f1911b1fa4f3419d9c4f
7
+ data.tar.gz: a4e067dccc15b8588ab721da6e12e5175be63febce3b25198178324944e60b248a1e9927c23b738beba4df6752525c451a8eeaf65553bacf79a017a069a4dbb4
@@ -1,8 +1,29 @@
1
+ ## 2.0.0
2
+
3
+ * [BREAKING] Do not activate `options[:converters]` by default
4
+ * [BREAKING] Remove *pleasant_path* dependency. This is considered a
5
+ breaking change because *pleasant_path* adds extension methods to
6
+ several Ruby core classes that consumer code may depend on.
7
+ * [BREAKING] Remove `append_to_file` instance method
8
+ * [BREAKING] Rename `each_in_file` class method to `read_each`
9
+ * Add `parse_each` class method
10
+ * Rename `parse_file` class method to `read`, and alias as `parse_file`
11
+ * Rename `parse_text` class method to `parse`, and alias as `parse_text`
12
+ * Add `write` class method
13
+ * Add `append` class method
14
+ * Add `eol` parameter to `to_s` instance method
15
+ * Add `DumbDelimited.csv`, `.psv`, and `.tsv` convenience shortcuts
16
+ * Activate `options[:liberal_parsing]` by default
17
+ * Make `options` inheritable
18
+ * Fix behavior when `options[:headers]` is set
19
+ * Fix behavior when `options[:write_headers]` is set
20
+
21
+
1
22
  ## 1.1.0
2
23
 
3
- * Fixed gem load on case-sensitive file systems.
4
- * Added `parse_text` class method.
5
- * Added `append_to_file` instance method.
24
+ * Add `parse_text` class method
25
+ * Add `append_to_file` instance method
26
+ * Fix gem load on case-sensitive file systems
6
27
 
7
28
 
8
29
  ## 1.0.0
data/README.md CHANGED
@@ -33,7 +33,7 @@ used as a superclass or simply assigned to a constant.
33
33
  ```ruby
34
34
  class Product < DumbDelimited[:sku, :name, :base_price, :sale_price]
35
35
  def on_sale?
36
- sale_price < base_price
36
+ sale_price.to_f < base_price.to_f
37
37
  end
38
38
  end
39
39
 
@@ -42,57 +42,71 @@ Customer.delimiter = "|"
42
42
  ```
43
43
 
44
44
  Because "customers.psv" is pipe-delimited, we also set the delimiter
45
- for the Customer class. By default, model classes use comma (`","`) as
46
- the delimiter. Whenever a delimiter is set, it applies to all future
45
+ for the Customer class. By default, a model class uses a comma (`","`)
46
+ as its delimiter. Whenever a delimiter is set, it applies to all future
47
47
  IO operations for that model class.
48
48
 
49
- Now we can read each flat file, and recieve an array of model objects.
49
+ Convenience shortcuts that create a model class and set its delimiter
50
+ are also provided for a few common delimiters. Notably,
51
+ `DumbDelimited::psv` for a model class with a pipe (`"|"`) delimiter.
52
+ Thus, the `Customer` class could alternatively be written as:
50
53
 
51
54
  ```ruby
52
- products = Product.parse_file("products.csv")
53
- customers = Customer.parse_file("customers.psv")
55
+ Customer = DumbDelimited.psv(:name, :email, :address)
54
56
  ```
55
57
 
56
- This, however, will load the entire contents of each file into memory.
58
+ Using our model classes, we can read each flat file, and recieve an
59
+ array of model objects:
60
+
61
+ ```ruby
62
+ products = Product.read("products.csv")
63
+ customers = Customer.read("customers.psv")
64
+ ```
65
+
66
+ However, this will load the entire contents of each file into memory.
57
67
  Let's say our customers file is very large, and we would prefer to
58
- iterate over it rather than load it all into memory at once. To do so,
59
- we can use the `each_in_file` method that the model class provides.
60
- Below is a complete example in which we load our product data, create a
61
- listing of products on sale, and iterate over our customers, notifying
62
- each customer of the sale products:
68
+ iterate over it one row at a time rather than load it all into memory at
69
+ once. To do so, we can use the `read_each` method. Below is a complete
70
+ example in which we load our product data, create a listing of products
71
+ on sale, and iterate over our customers, notifying each customer of the
72
+ sale products:
63
73
 
64
74
  ```ruby
65
- products = Product.parse_file("products.csv")
75
+ products = Product.read("products.csv")
66
76
 
67
77
  listing = products.select(&:on_sale?).map do |product|
68
78
  "* #{product.name} (#{product.sale_price})"
69
79
  end.join("\n")
70
80
 
71
- Customer.each_in_file("customers.psv") do |customer|
72
- message =
73
- "Hi #{customer.name}!\n\n" \
74
- "The following products are on sale:\n\n#{listing}"
81
+ Customer.read_each("customers.psv") do |customer|
82
+ message = <<~MESSAGE
83
+ Hi #{customer.name}!
84
+
85
+ The following products are on sale:
86
+
87
+ #{listing}
88
+ MESSAGE
75
89
 
76
90
  notify(customer.email, message)
77
91
  end
78
92
  ```
79
93
 
80
94
  Let's say the sale is now over, and we want to change our sale prices
81
- back to our base prices. *dumb_delimited* includes the
82
- [*pleasant_path*](https://rubygems.org/gems/pleasant_path) gem, which
83
- offers a fluent API for writing files. To finish our task, we use the
84
- `Array#write_to_file` method provided by *pleasant_path*, which in turn
85
- invokes `Product#to_s` (provided by *dumb_delimited*) on each model
86
- object.
95
+ back to our base prices. We can load our product data, modify it
96
+ directly, and finally persist it back with the `write` method:
87
97
 
88
98
  ```ruby
89
- Product.parse_file("products.csv").each do |product|
99
+ products = Product.read("products.csv")
100
+
101
+ products.each do |product|
90
102
  product.sale_price = product.base_price
91
- end.write_to_file("products.csv")
103
+ end
104
+
105
+ Product.write("products.csv", products)
92
106
  ```
93
107
 
94
108
  For a more detailed explanation of the *dumb_delimited* API, browse the
95
- [full documentation](http://www.rubydoc.info/gems/dumb_delimited/).
109
+ [API documentation](http://www.rubydoc.info/gems/dumb_delimited/).
96
110
 
97
111
 
98
112
  ## Installation
@@ -20,8 +20,6 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_runtime_dependency "pleasant_path", "~> 1.0"
24
-
25
23
  spec.add_development_dependency "bundler", "~> 1.15"
26
24
  spec.add_development_dependency "rake", "~> 10.0"
27
25
  spec.add_development_dependency "minitest", "~> 5.0"
@@ -1,28 +1,29 @@
1
1
  require "csv"
2
- require "pleasant_path"
3
2
  require_relative "dumb_delimited/version"
4
3
 
5
4
 
6
5
  module DumbDelimited
7
6
 
8
7
  # Returns a model class for delimited data consisting of the specified
9
- # columns. The returned class inherits from Ruby's
10
- # {https://ruby-doc.org/core/Struct.html +Struct+}, allowing data
11
- # manipulation via accessor methods, via indexing by column name, and
12
- # via indexing by column number. See {ClassMethods} and
13
- # {InstanceMethods} for the IO methods the returned class provides.
8
+ # +columns+. The returned class inherits from Ruby's
9
+ # {https://docs.ruby-lang.org/en/trunk/Struct.html +Struct+}, allowing
10
+ # data manipulation via accessor methods, via indexing by column name,
11
+ # and via indexing by column number. See {ClassMethods} and
12
+ # {InstanceMethods} for the additional methods the returned class
13
+ # provides.
14
14
  #
15
15
  # @example
16
16
  # class Product < DumbDelimited[:sku, :name, :base_price, :sale_price]
17
17
  # def on_sale?
18
- # sale_price < base_price
18
+ # sale_price.to_f < base_price.to_f
19
19
  # end
20
20
  # end
21
21
  #
22
+ # @example
22
23
  # Customer = DumbDelimited[:name, :email, :address]
23
24
  #
24
- # @param columns [*Symbol]
25
- # @return [Class]
25
+ # @param columns [Array<Symbol>]
26
+ # @return [Class<Struct>]
26
27
  def self.[](*columns)
27
28
  Struct.new(*columns) do
28
29
  extend DumbDelimited::ClassMethods
@@ -30,42 +31,111 @@ module DumbDelimited
30
31
  end
31
32
  end
32
33
 
34
+ # Convenience shortcut to create a model class and set
35
+ # {ClassMethods#delimiter} to +","+.
36
+ #
37
+ # Note: This method exists mostly for parity with {psv} and {tsv}.
38
+ # Unless +CSV::DEFAULT_OPTIONS+ has been modified, the delimiter will
39
+ # already default to +","+.
40
+ #
41
+ # @example
42
+ # # This...
43
+ # Point = DumbDelimited.csv(:x, :y, :z)
44
+ #
45
+ # # ...is equivalent to:
46
+ # Point = DumbDelimited[:x, :y, :z]
47
+ # Point.delimiter = ","
48
+ #
49
+ # @param columns [Array<Symbol>]
50
+ # @return [Class<Struct>]
51
+ def self.csv(*columns)
52
+ klass = self[*columns]
53
+ klass.delimiter = ","
54
+ klass
55
+ end
56
+
57
+ # Convenience shortcut to create a model class and set
58
+ # {ClassMethods#delimiter} to +"|"+.
59
+ #
60
+ # @example
61
+ # # This...
62
+ # Point = DumbDelimited.psv(:x, :y, :z)
63
+ #
64
+ # # ...is equivalent to:
65
+ # Point = DumbDelimited[:x, :y, :z]
66
+ # Point.delimiter = "|"
67
+ #
68
+ # @param columns [Array<Symbol>]
69
+ # @return [Class<Struct>]
70
+ def self.psv(*columns)
71
+ klass = self[*columns]
72
+ klass.delimiter = "|"
73
+ klass
74
+ end
75
+
76
+ # Convenience shortcut to create a model class and set
77
+ # {ClassMethods#delimiter} to <code>"\t"</code>.
78
+ #
79
+ # @example
80
+ # # This...
81
+ # Point = DumbDelimited.tsv(:x, :y, :z)
82
+ #
83
+ # # ...is equivalent to:
84
+ # Point = DumbDelimited[:x, :y, :z]
85
+ # Point.delimiter = "\t"
86
+ #
87
+ # @param columns [Array<Symbol>]
88
+ # @return [Class<Struct>]
89
+ def self.tsv(*columns)
90
+ klass = self[*columns]
91
+ klass.delimiter = "\t"
92
+ klass
93
+ end
94
+
33
95
  end
34
96
 
35
97
 
36
98
  module DumbDelimited::ClassMethods
37
99
 
38
- # Returns the advanced options Hash. The Hash is not +dup+ed and can
39
- # be modified directly. Any modifications will be applied to all
40
- # future IO operations for the model class. For detailed information
41
- # about available options, see Ruby's
42
- # {http://ruby-doc.org/stdlib/libdoc/csv/rdoc/CSV.html#method-c-new
43
- # CSV module}.
100
+ # Returns the CSV options Hash. The Hash is not +dup+ed and can be
101
+ # modified directly. Any modifications will be applied to all future
102
+ # IO operations for the model class.
44
103
  #
45
- # @return [Hash]
104
+ # For detailed information about available options, see Ruby's
105
+ # {https://docs.ruby-lang.org/en/trunk/CSV.html#method-c-new CSV
106
+ # class}.
107
+ #
108
+ # @return [Hash<Symbol, Object>]
46
109
  def options
47
- @options ||= {
48
- col_sep: ",",
49
- skip_blanks: true,
50
- converters: :numeric,
51
- }
110
+ @options ||= if superclass == Struct
111
+ CSV::DEFAULT_OPTIONS.merge(
112
+ skip_blanks: true,
113
+ liberal_parsing: true,
114
+ )
115
+ else
116
+ superclass.options.dup
117
+ end
52
118
  end
53
119
 
54
- # Sets the advanced options Hash. The entire Hash is replaced, and
55
- # the new value will be applied to all future IO operations for the
56
- # model class. To set options individually, see {options}. For
57
- # detailed information about available options, see Ruby's
58
- # {http://ruby-doc.org/stdlib/libdoc/csv/rdoc/CSV.html#method-c-new
59
- # CSV module}.
120
+ # Sets the CSV options Hash. The entire Hash is replaced, and the new
121
+ # values will be applied to all future IO operations for the model
122
+ # class. To set options individually, see {options}.
60
123
  #
61
- # @param o [Hash]
62
- def options=(o)
63
- @options = o
124
+ # For detailed information about available options, see Ruby's
125
+ # {https://docs.ruby-lang.org/en/trunk/CSV.html#method-c-new CSV
126
+ # class}.
127
+ #
128
+ # @param opts [Hash<Symbol, Object>]
129
+ # @return [Hash<Symbol, Object>]
130
+ def options=(opts)
131
+ @options = opts
64
132
  end
65
133
 
66
134
  # Returns the column delimiter used in IO operations. Defaults to a
67
135
  # comma (<code>","</code>).
68
136
  #
137
+ # Equivalent to <code>options[:col_sep]</code>.
138
+ #
69
139
  # @return [String]
70
140
  def delimiter
71
141
  self.options[:col_sep]
@@ -76,6 +146,8 @@ module DumbDelimited::ClassMethods
76
146
  # delimiter can be safely chosen, and all IO operations will quote
77
147
  # field values as necessary.
78
148
  #
149
+ # Equivalent to <code>options[:col_sep] = delim</code>.
150
+ #
79
151
  # @example
80
152
  # Point = DumbDelimited[:x, :y, :z]
81
153
  # p = Point.new(1, 2, 3)
@@ -83,9 +155,10 @@ module DumbDelimited::ClassMethods
83
155
  # Point.delimiter = "|"
84
156
  # p.to_s # == "1|2|3"
85
157
  #
86
- # @param d [String]
87
- def delimiter=(d)
88
- self.options[:col_sep] = d
158
+ # @param delim [String]
159
+ # @return [String]
160
+ def delimiter=(delim)
161
+ self.options[:col_sep] = delim
89
162
  end
90
163
 
91
164
  # Parses a single delimited line into a model object.
@@ -95,34 +168,53 @@ module DumbDelimited::ClassMethods
95
168
  # Point.parse_line("1,2,3") # == Point.new(1, 2, 3)
96
169
  #
97
170
  # @param line [String]
98
- # @return [self]
171
+ # @return [Struct]
99
172
  def parse_line(line)
100
- self.new(*CSV.parse_line(line, self.options))
173
+ parse_each(line).first
101
174
  end
102
175
 
103
- # Parses a string into an array of model objects.
176
+ # Parses a string or IO object into an array of model objects.
104
177
  #
105
178
  # @example
106
179
  # Point = DumbDelimited[:x, :y, :z]
107
- # Point.parse_text("1,2,3\n4,5,6\n7,8,9\n")
180
+ # Point.parse("1,2,3\n4,5,6\n7,8,9\n")
108
181
  # # == [
109
182
  # # Point.new(1, 2, 3),
110
183
  # # Point.new(4, 5, 6),
111
184
  # # Point.new(7, 8, 9)
112
185
  # # ]
113
186
  #
114
- # @param text [String]
115
- # @return [Array<self>]
116
- def parse_text(text)
117
- # using CSV.new.each instead of CSV.parse to avoid unnecessary mass
118
- # memory allocation and deallocation
119
- CSV.new(text, self.options).each.map{|row| self.new(*row) }
187
+ # @param data [String, IO]
188
+ # @return [Array<Struct>]
189
+ def parse(data)
190
+ parse_each(data).to_a
191
+ end
192
+
193
+ alias_method :parse_text, :parse
194
+
195
+ # Parses a string or IO object one line at a time, yielding a model
196
+ # object for each line.
197
+ #
198
+ # An Enumerator is returned if no block is given.
199
+ #
200
+ # @overload parse_each(data, &block)
201
+ # @param data [String, IO]
202
+ # @yieldparam model [Struct]
203
+ # @return [void]
204
+ #
205
+ # @overload parse_each(data)
206
+ # @param data [String, IO]
207
+ # @return [Enumerator<Struct>]
208
+ def parse_each(data, &block)
209
+ return to_enum(__method__, data) unless block_given?
210
+
211
+ csv_each(CSV.new(data, self.options), &block)
120
212
  end
121
213
 
122
- # Parses an entire delimited file into an array of model objects.
123
- # This will load the entire contents of the file into memory, and may
124
- # not be suitable for large files. To iterate over file contents
125
- # without loading it all into memory at once, use {each_in_file}.
214
+ # Parses a file into an array of model objects. This will load the
215
+ # entire contents of the file into memory, and may not be suitable for
216
+ # large files. To iterate over file contents without loading it all
217
+ # into memory at once, use {read_each}.
126
218
  #
127
219
  # @example
128
220
  # # CONTENTS OF FILE "points.csv":
@@ -131,7 +223,7 @@ module DumbDelimited::ClassMethods
131
223
  # # 7,8,9
132
224
  #
133
225
  # Point = DumbDelimited[:x, :y, :z]
134
- # Point.parse_file("points.csv")
226
+ # Point.read("points.csv")
135
227
  # # == [
136
228
  # # Point.new(1, 2, 3),
137
229
  # # Point.new(4, 5, 6),
@@ -139,27 +231,77 @@ module DumbDelimited::ClassMethods
139
231
  # # ]
140
232
  #
141
233
  # @param path [String, Pathname]
142
- # @return [Array<self>]
143
- def parse_file(path)
144
- each_in_file(path).to_a
234
+ # @return [Array<Struct>]
235
+ def read(path)
236
+ read_each(path).to_a
145
237
  end
146
238
 
147
- # Iterates over a delimited file, parsing one row at a time into model
148
- # objects. This avoids loading the entire contents of the file into
149
- # memory at once. If a block is given, it will be passed a model
150
- # object for each row in the file. Otherwise, if a block is not
151
- # given, an Enumerator will be returned. Note that some Enumerator
152
- # methods, such as +Enumerator#to_a+, will cause the entire contents
153
- # of the file to be loaded into memory regardless.
239
+ alias_method :parse_file, :read
240
+
241
+ # Parses a file one line at a time, yielding a model object for each
242
+ # line. This avoids loading the entire contents of the file into
243
+ # memory at once.
154
244
  #
155
- # @param path [String, Pathname]
156
- # @yieldparam [self] current model object
157
- # @return [Enumerator<self>, nil]
158
- def each_in_file(path)
245
+ # An Enumerator is returned if no block is given. Note that some
246
+ # Enumerator methods, such as +Enumerator#to_a+, can cause the entire
247
+ # contents of the file to be loaded into memory.
248
+ #
249
+ # @overload read_each(path, &block)
250
+ # @param path [String, Pathname]
251
+ # @yieldparam model [Struct]
252
+ # @return [void]
253
+ #
254
+ # @overload read_each(path)
255
+ # @param path [String, Pathname]
256
+ # @return [Enumerator<Struct>]
257
+ def read_each(path, &block)
159
258
  return to_enum(__method__, path) unless block_given?
160
259
 
161
- CSV.foreach(path, self.options) do |row|
162
- yield self.new(*row)
260
+ CSV.open(path, self.options) do |csv|
261
+ csv_each(csv, &block)
262
+ end
263
+ end
264
+
265
+ # Writes a collection of model objects to a file in delimited format.
266
+ # The previous contents of the file are overwritten, unless +append+
267
+ # is set to true.
268
+ #
269
+ # Column headers are written to the file if +:write_headers+ in
270
+ # {options} is set to true *and* either +append+ is false or the file
271
+ # is empty / non-existent. The column headers will be derived from
272
+ # either the value of +:headers+ in {options} if it is an Array, or
273
+ # otherwise from the columns defined by the model.
274
+ #
275
+ # @param path [String, Pathname]
276
+ # @param models [Enumerable<Struct>]
277
+ # @param append [Boolean]
278
+ # @return [void]
279
+ def write(path, models, append: false)
280
+ mode = append ? "a" : "w"
281
+ write_headers = options[:write_headers] && !(append && File.exist?(path) && File.size(path) > 0)
282
+ headers = (!options[:headers].is_a?(Array) && write_headers) ? members : options[:headers]
283
+
284
+ CSV.open(path, mode, **options, write_headers: write_headers, headers: headers) do |csv|
285
+ models.each{|model| csv << model }
286
+ end
287
+ end
288
+
289
+ # Appends a collection of model objects to a file in delimited format.
290
+ # Convenience shortcut for {write} with +append: true+.
291
+ #
292
+ # @param path [String, Pathname]
293
+ # @param models [Enumerable<Struct>]
294
+ # @return [void]
295
+ def append(path, models)
296
+ write(path, models, append: true)
297
+ end
298
+
299
+ private
300
+
301
+ def csv_each(csv, &block)
302
+ csv.each do |row|
303
+ row = row.fields if row.is_a?(CSV::Row)
304
+ block.call(self.new(*row))
163
305
  end
164
306
  end
165
307
 
@@ -169,33 +311,19 @@ end
169
311
  module DumbDelimited::InstanceMethods
170
312
 
171
313
  # Serializes a model object to a delimited string, using the delimiter
172
- # specified by {ClassMethods.delimiter}.
314
+ # specified by {ClassMethods#delimiter}. By default, the string will
315
+ # not end with a line terminator. To end the string with a line
316
+ # terminator designated by +:row_sep+ in {ClassMethods#options}, set
317
+ # +eol+ to true.
173
318
  #
319
+ # @param eol [Boolean]
174
320
  # @return [String]
175
- def to_s
176
- CSV.generate_line(self, self.class.options).chomp!
177
- end
321
+ def to_s(eol = false)
322
+ row_sep = eol ? self.class.options[:row_sep] : -""
178
323
 
179
- # Serializes a model object to a delimited string, using the delimiter
180
- # specified by {ClassMethods.delimiter}, and appends the string plus a
181
- # row separator to the specified file. Returns the model object.
182
- # This method is convenient when working with single model objects,
183
- # for example, appending a single entry to a log file. However, it is
184
- # not recommended for use with an array of model objects, due to the
185
- # overhead of opening and closing the file for each append.
186
- #
187
- # @example
188
- # Point = DumbDelimited[:x, :y, :z]
189
- # Point.new(1, 2, 3).append_to_file("out.txt") # == Point.new(1, 2, 3)
190
- # File.read("out.txt") # == "1,2,3\n"
191
- # Point.new(4, 5, 6).append_to_file("out.txt") # == Point.new(4, 5, 6)
192
- # File.read("out.txt") # == "1,2,3\n4,5,6\n"
193
- #
194
- # @param file [String, Pathname]
195
- # @return [self]
196
- def append_to_file(file)
197
- CSV.generate_line(self, self.class.options).append_to_file(file)
198
- self
324
+ CSV.generate(**self.class.options, row_sep: row_sep, write_headers: false) do |csv|
325
+ csv << self
326
+ end
199
327
  end
200
328
 
201
329
  end
@@ -1,3 +1,3 @@
1
1
  module DumbDelimited
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dumb_delimited
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Hefner
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-16 00:00:00.000000000 Z
11
+ date: 2019-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: pleasant_path
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -116,8 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
102
  - !ruby/object:Gem::Version
117
103
  version: '0'
118
104
  requirements: []
119
- rubyforge_project:
120
- rubygems_version: 2.7.6
105
+ rubygems_version: 3.0.1
121
106
  signing_key:
122
107
  specification_version: 4
123
108
  summary: Library for unsophisticated delimited flat file IO