rsmart_toolbox 0.5 → 0.6
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/rsmart_toolbox/etl.rb +119 -38
- data/lib/rsmart_toolbox/etl/grm.rb +19 -0
- data/lib/rsmart_toolbox/version.rb +1 -1
- data/spec/rsmart_toolbox/etl_spec.rb +6 -6
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27fabd26f64bc774e3d4bbfefd30d7cc519bd561
|
4
|
+
data.tar.gz: 888167314f2c75e27f67461cdf8592f9f394440f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e75b6da705654223a6ff1b8f36eb9d049c46511448d7eb8da9d2512f27b82b63f4c006d15dc85c03c592b7e713e7ec41687da6156581eba30754d4719294cb79
|
7
|
+
data.tar.gz: 3fc723d8d3595c88425cf35fdcd2a518f5c67bf2f71153ce9702a097660f84c75522a40ea7f8d20e2a35bf87041567bf57d33527e538df34e5bcf42505979597
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/rsmart_toolbox/etl.rb
CHANGED
@@ -21,7 +21,8 @@ module Rsmart::ETL
|
|
21
21
|
class TextParseError < StandardError
|
22
22
|
end
|
23
23
|
|
24
|
-
#
|
24
|
+
# @param [String, Exception] e the error to handle
|
25
|
+
# @return [Exception] an Exception with a message formatted with $INPUT_LINE_NUMBER.
|
25
26
|
def self.error(e)
|
26
27
|
if e.kind_of? String
|
27
28
|
# default to TextParseError
|
@@ -33,7 +34,8 @@ module Rsmart::ETL
|
|
33
34
|
raise ArgumentError, "Unsupported error type: #{e.class}"
|
34
35
|
end
|
35
36
|
|
36
|
-
#
|
37
|
+
# @param [String, Exception] e the warning to handle
|
38
|
+
# @return [Exception] an Exception with a message formatted with $INPUT_LINE_NUMBER.
|
37
39
|
def self.warning(e)
|
38
40
|
if e.kind_of? String
|
39
41
|
# default to TextParseError
|
@@ -45,7 +47,14 @@ module Rsmart::ETL
|
|
45
47
|
raise ArgumentError, "Unsupported error type: #{e.class}"
|
46
48
|
end
|
47
49
|
|
48
|
-
#
|
50
|
+
# @param [String, #match] subject used for validity checking.
|
51
|
+
# @param [Array<Object>, Regexp] valid_values all of the possible valid values.
|
52
|
+
# @option opt [Boolean] :case_sensitive performs case sensitive matching
|
53
|
+
# @return [Boolean] true if the subject matches valid_values.
|
54
|
+
# FYI valid_values must respond to #casecmp.
|
55
|
+
# @raise [ArgumentError] if valid_values is nil or empty.
|
56
|
+
# @raise [ArgumentError] case sensitive matching only works for objects
|
57
|
+
# that respond to #casecmp; primarily String objects.
|
49
58
|
def self.valid_value(subject, valid_values, opt={})
|
50
59
|
raise ArgumentError, "valid_values must not be nil!" if valid_values.nil?
|
51
60
|
if valid_values.kind_of? Regexp
|
@@ -54,7 +63,7 @@ module Rsmart::ETL
|
|
54
63
|
if valid_values.kind_of? Array
|
55
64
|
raise ArgumentError, "valid_values must have at least one element!" unless valid_values.length > 0
|
56
65
|
if opt[:case_sensitive] == false # case insensitive comparison requested
|
57
|
-
raise ArgumentError, "
|
66
|
+
raise ArgumentError, "Object must respond to #casecmp" unless subject.respond_to? 'casecmp'
|
58
67
|
valid_values.each do |valid_value|
|
59
68
|
return true if valid_value.casecmp(subject) == 0
|
60
69
|
end
|
@@ -64,6 +73,10 @@ module Rsmart::ETL
|
|
64
73
|
return false
|
65
74
|
end
|
66
75
|
|
76
|
+
# @param [String] str String to be matched against well known boolean patterns.
|
77
|
+
# @option opt [Boolean] :default the default return value if str is empty.
|
78
|
+
# @return [Boolean] the result of matching the str input against well known boolean patterns.
|
79
|
+
# @raise [TextParseError] if none of the known boolean patterns could be matched.
|
67
80
|
def self.parse_boolean(str, opt={})
|
68
81
|
return true if str == true
|
69
82
|
return false if str == false
|
@@ -79,22 +92,34 @@ module Rsmart::ETL
|
|
79
92
|
raise Rsmart::ETL::error TextParseError.new "invalid value for Boolean: '#{str}'"
|
80
93
|
end
|
81
94
|
|
82
|
-
#
|
83
|
-
|
95
|
+
# @param [String] str the String to be encoded and invalid characters replaced with valid characters.
|
96
|
+
# @option opt [String] :encoding the character encoding to use.
|
97
|
+
# @return [String] the result of encoding the String and replacing invalid characters with valid characters.
|
98
|
+
def self.encode(str, opt={ encoding: "UTF-8" } )
|
84
99
|
opt[:encoding] = "UTF-8" if opt[:encoding].nil?
|
85
100
|
str.encode( opt[:encoding], :invalid => :replace,
|
86
101
|
:undef => :replace, :replace => "" )
|
87
102
|
end
|
88
103
|
|
89
|
-
# Matches MRI CSV specification:
|
104
|
+
# Matches the MRI CSV specification:
|
90
105
|
# The header String is downcased, spaces are replaced with underscores,
|
91
106
|
# non-word characters are dropped, and finally to_sym() is called.
|
107
|
+
# @param [String] str the String to be symbolized.
|
108
|
+
# @return [Symbol] String is downcased, spaces are replaced with underscores,
|
109
|
+
# non-word characters are dropped
|
110
|
+
# @raise [ArgumentError] if str is nil or empty.
|
92
111
|
def self.to_symbol(str)
|
93
112
|
raise ArgumentError, "Illegal symbol name: '#{str}'" if str.nil? || str.empty?
|
94
113
|
encode( str.downcase.gsub(/\s+/, "_").gsub(/\W+/, "") ).to_sym
|
95
114
|
end
|
96
115
|
|
97
|
-
#
|
116
|
+
# Mutates insert_str and values_str with column_name and value respectively.
|
117
|
+
# Proper SQL value quoting will be performed based on object type.
|
118
|
+
# @param [String] insert_str the left side of the insert statement (i.e. columns)
|
119
|
+
# @param [String] column_name the column name to append to insert_str.
|
120
|
+
# @param [String] values_str the right side of the insert statement (i.e. values)
|
121
|
+
# @param [Object] value the value to append to values_str. Must respond to #to_s.
|
122
|
+
# @return [void]
|
98
123
|
def self.mutate_sql_stmt!(insert_str, column_name, values_str, value)
|
99
124
|
insert_str.concat "#{column_name.upcase},"
|
100
125
|
# TODO what are all of the valid types that should not be quoted?
|
@@ -103,8 +128,13 @@ module Rsmart::ETL
|
|
103
128
|
else
|
104
129
|
values_str.concat "'#{value}',"
|
105
130
|
end
|
131
|
+
return nil
|
106
132
|
end
|
107
133
|
|
134
|
+
# Prepares a String for a SQL statement where single quotes need to be escaped.
|
135
|
+
# @param [String] str the String to be escaped.
|
136
|
+
# @return [String, nil] the resulting String with single quotes escaped with a backslash.
|
137
|
+
# If a nil is passed, nil is returned.
|
108
138
|
def self.escape_single_quotes(str)
|
109
139
|
if str.nil?
|
110
140
|
return nil
|
@@ -112,14 +142,31 @@ module Rsmart::ETL
|
|
112
142
|
return str.to_s.gsub("'", "\\\\'")
|
113
143
|
end
|
114
144
|
|
115
|
-
|
116
|
-
|
145
|
+
# @param [String] str the String to be parsed.
|
146
|
+
# @option opt [String, #to_s] :default the default return value if str is empty. Must respond to #to_s
|
147
|
+
# @option opt [Boolean] :escape_single_quotes escape single quote characters.
|
148
|
+
# @option opt [Integer] :length raise a TextParseError if str.length > :length.
|
149
|
+
# @option opt [String] :name the name of the field being parsed. Used only for error handling.
|
150
|
+
# @option opt [Boolean] :required raise a TextParseError if str is empty.
|
151
|
+
# @option opt [Boolean] :strict strict length checking will produce errors instead of warnings.
|
152
|
+
# @option opt [Array<Object>, Regexp] :valid_values all of the possible valid values.
|
153
|
+
# @return [String] the parsed results. nil or empty inputs will return the empty String by default(i.e. '').
|
154
|
+
# @raise [TextParseError] if the field is :required and found to be empty.
|
155
|
+
# @raise [TextParseError] if str.length > :length && :strict
|
156
|
+
# @raise [TextParseError] if str does not match :valid_values
|
157
|
+
# @example nil or empty inputs will return the empty String by default
|
158
|
+
# '' == parse_string(nil) && '' == parse_string('')
|
159
|
+
# @see valid_value
|
160
|
+
# @see escape_single_quotes
|
161
|
+
def self.parse_string(str, opt={ strict: true, required: false, escape_single_quotes: true })
|
162
|
+
opt[:strict] = true if opt[:strict].nil?
|
163
|
+
opt[:escape_single_quotes] = true if opt[:escape_single_quotes].nil?
|
117
164
|
retval = encode str.to_s.strip
|
118
165
|
if opt[:required] && retval.empty?
|
119
166
|
raise Rsmart::ETL::error TextParseError.new "Required data element '#{opt[:name]}' not found: '#{str}'"
|
120
167
|
end
|
121
168
|
if opt[:default] && retval.empty?
|
122
|
-
retval = opt[:default]
|
169
|
+
retval = opt[:default].to_s
|
123
170
|
end
|
124
171
|
if opt[:length] && retval.length > opt[:length].to_i
|
125
172
|
detail = "#{opt[:name]}.length > #{opt[:length]}: '#{str}'-->'#{str[0..(opt[:length] - 1)]}'"
|
@@ -131,15 +178,36 @@ module Rsmart::ETL
|
|
131
178
|
if opt[:valid_values] && ! valid_value(retval, opt[:valid_values], opt)
|
132
179
|
raise Rsmart::ETL::error TextParseError.new "Illegal #{opt[:name]}: value '#{str}' not found in: #{opt[:valid_values]}"
|
133
180
|
end
|
134
|
-
|
181
|
+
if opt[:escape_single_quotes]
|
182
|
+
retval = escape_single_quotes retval
|
183
|
+
end
|
184
|
+
return retval
|
135
185
|
end
|
136
186
|
|
187
|
+
# Helper method which finds the value by column :name and mutates the SQL statement accordingly.
|
188
|
+
# @param [CSV::Row] row the CSV Row being parsed
|
189
|
+
# @param [String] insert_str the left side of the insert statement (i.e. columns)
|
190
|
+
# @param [String] values_str the right side of the insert statement (i.e. values)
|
191
|
+
# @param [Hash] opt options Hash will be passed through to #parse_string.
|
192
|
+
# @option opt [String] :name the name of the field being parsed. Required.
|
193
|
+
# @return [void]
|
194
|
+
# @raise [ArgumentError] :name is required.
|
195
|
+
# @see parse_string
|
196
|
+
# @see mutate_sql_stmt!
|
137
197
|
def self.parse_string!(row, insert_str, values_str, opt={})
|
138
198
|
raise ArgumentError, "opt[:name] is required!" unless opt[:name]
|
139
199
|
str = parse_string( row[ to_symbol( opt[:name] ) ], opt )
|
140
200
|
mutate_sql_stmt! insert_str, opt[:name], values_str, str
|
141
201
|
end
|
142
202
|
|
203
|
+
# Parse an Integer from a String.
|
204
|
+
# @note Note the behavioral difference versus #to_i.
|
205
|
+
# @param [String] str the String to be parsed.
|
206
|
+
# @param [Hash] opt options Hash will be passed through to #parse_string.
|
207
|
+
# @return [Integer, nil] the parsed Integer. nil or empty inputs will return nil by default.
|
208
|
+
# @example Unlike #to_i, nil or empty inputs will return nil by default
|
209
|
+
# nil == parse_integer(nil) && nil == parse_integer('') && 0 != parse_integer(nil)
|
210
|
+
# @see parse_string
|
143
211
|
def self.parse_integer(str, opt={})
|
144
212
|
s = parse_string str, opt
|
145
213
|
if s.empty?
|
@@ -149,12 +217,30 @@ module Rsmart::ETL
|
|
149
217
|
end
|
150
218
|
end
|
151
219
|
|
220
|
+
# Helper method which finds the value by column :name and mutates the SQL statement accordingly.
|
221
|
+
# @param [CSV::Row] row the CSV Row being parsed
|
222
|
+
# @param [String] insert_str the left side of the insert statement (i.e. columns)
|
223
|
+
# @param [String] values_str the right side of the insert statement (i.e. values)
|
224
|
+
# @param [Hash] opt options Hash will be passed through to #parse_integer.
|
225
|
+
# @option opt [String] :name the name of the field being parsed. Required.
|
226
|
+
# @return [void]
|
227
|
+
# @raise [ArgumentError] :name is required.
|
228
|
+
# @see parse_integer
|
229
|
+
# @see mutate_sql_stmt!
|
152
230
|
def self.parse_integer!(row, insert_str, values_str, opt={})
|
153
231
|
raise ArgumentError, "opt[:name] is required!" unless opt[:name]
|
154
232
|
i = parse_integer( row[ to_symbol( opt[:name] ) ], opt )
|
155
233
|
mutate_sql_stmt! insert_str, opt[:name], values_str, i
|
156
234
|
end
|
157
235
|
|
236
|
+
# Parse a Float from a String.
|
237
|
+
# @note Note the behavioral difference versus #to_f.
|
238
|
+
# @param [String] str the String to be parsed.
|
239
|
+
# @param [Hash] opt options Hash will be passed through to #parse_string.
|
240
|
+
# @return [Float, nil] the parsed Float. nil or empty inputs will return nil by default.
|
241
|
+
# @example Unlike #to_f, nil or empty inputs will return nil by default
|
242
|
+
# nil == parse_float(nil) && nil == parse_float('') && 0.0 != parse_float(nil)
|
243
|
+
# @see parse_string
|
158
244
|
def self.parse_float(str, opt={})
|
159
245
|
s = parse_string str, opt
|
160
246
|
if s.empty?
|
@@ -164,9 +250,14 @@ module Rsmart::ETL
|
|
164
250
|
end
|
165
251
|
end
|
166
252
|
|
167
|
-
# Useful for parsing "flag" like values.
|
168
|
-
#
|
169
|
-
|
253
|
+
# Useful for parsing "flag" like values; i.e. usually single characters.
|
254
|
+
# @param [String] str the String to be parsed.
|
255
|
+
# @param [Hash] opt options Hash will be passed through to #parse_string.
|
256
|
+
# @option opt [Integer] :length the maximum supported length of the field.
|
257
|
+
# @option opt [Boolean] :upcase if true upcase the results.
|
258
|
+
# @return [String] the parsed "flag".
|
259
|
+
# @see parse_string
|
260
|
+
def self.parse_flag(str, opt={ length: 1, upcase: true })
|
170
261
|
opt[:length] = 1 if opt[:length].nil?
|
171
262
|
opt[:upcase] = true if opt[:upcase].nil?
|
172
263
|
retval = parse_string str, opt
|
@@ -174,32 +265,22 @@ module Rsmart::ETL
|
|
174
265
|
return retval
|
175
266
|
end
|
176
267
|
|
177
|
-
# Designed specifically for actv_ind, but could be used on *any*
|
178
|
-
# fields that matches /^(Y|N)$/i.
|
179
|
-
def self.parse_actv_ind(str, opt={})
|
180
|
-
# `ACTV_IND` varchar(1) COLLATE utf8_bin DEFAULT 'Y',
|
181
|
-
opt[:name] = "actv_ind" if opt[:name].nil?
|
182
|
-
opt[:default] = "Y" if opt[:default].nil?
|
183
|
-
opt[:valid_values] = /^(Y|N)$/i if opt[:valid_values].nil?
|
184
|
-
return parse_flag str, opt
|
185
|
-
end
|
186
|
-
|
187
|
-
# Designed specifically for actv_ind, but could be used on *any*
|
188
|
-
# fields that matches /^(Y|N)$/i.
|
189
|
-
def self.parse_actv_ind!(row, insert_str, values_str, opt={})
|
190
|
-
# `ACTV_IND` varchar(1) COLLATE utf8_bin DEFAULT 'Y',
|
191
|
-
opt[:name] = "actv_ind" if opt[:name].nil?
|
192
|
-
actv_ind = Rsmart::ETL::parse_actv_ind row[ to_symbol( opt[:name] ) ]
|
193
|
-
Rsmart::ETL::mutate_sql_stmt! insert_str, opt[:name], values_str, actv_ind
|
194
|
-
end
|
195
|
-
|
196
268
|
# Parse common command line options for CSV --> SQL transformations.
|
269
|
+
# @param [String] executable the name of the script from which we are executing. See example.
|
270
|
+
# @param [Array<String>] args the command line args.
|
271
|
+
# @option opt [String] :csv_filename the input file from which the CSV will be read.
|
272
|
+
# Defaults to the first element of args Array.
|
273
|
+
# @option opt [String] :sql_filename the output file to which the SQL will be written.
|
274
|
+
# @option opt [Hash] :csv_options the options that will be used by the CSV parser.
|
275
|
+
# @return [Hash] a Hash containing the parsed command line results.
|
276
|
+
# @example The most common usage:
|
277
|
+
# opt = Rsmart::ETL.parse_csv_command_line_options (File.basename $0), ARGF.argv
|
197
278
|
def self.parse_csv_command_line_options(
|
198
279
|
executable, args, opt={ csv_options: { headers: :first_row,
|
199
280
|
header_converters: :symbol,
|
200
281
|
skip_blanks: true,
|
201
|
-
col_sep: ",",
|
202
|
-
quote_char: '"'
|
282
|
+
col_sep: ",",
|
283
|
+
quote_char: '"'
|
203
284
|
}
|
204
285
|
} )
|
205
286
|
optparse = OptionParser.new do |opts|
|
@@ -208,10 +289,10 @@ module Rsmart::ETL
|
|
208
289
|
opt[:sql_filename] = f
|
209
290
|
end
|
210
291
|
opts.on( '-s [separator_character]' ,'--separator [separator_character]', 'The character that separates each column of the CSV file.') do |s|
|
211
|
-
opt[:col_sep] = s
|
292
|
+
opt[:csv_options][:col_sep] = s
|
212
293
|
end
|
213
294
|
opts.on( '-q [quote_character]' ,'--quote [quote_character]', 'The character used to quote fields.') do |q|
|
214
|
-
opt[:quote_char] = q
|
295
|
+
opt[:csv_options][:quote_char] = q
|
215
296
|
end
|
216
297
|
opts.on( '-h', '--help', 'Display this screen' ) do
|
217
298
|
puts opts
|
@@ -187,4 +187,23 @@ module Rsmart::ETL::GRM
|
|
187
187
|
return Rsmart::ETL::parse_flag str, opt
|
188
188
|
end
|
189
189
|
|
190
|
+
# Designed specifically for actv_ind, but could be used on *any*
|
191
|
+
# fields that matches /^(Y|N)$/i.
|
192
|
+
def self.parse_actv_ind(str, opt={})
|
193
|
+
# `ACTV_IND` varchar(1) COLLATE utf8_bin DEFAULT 'Y',
|
194
|
+
opt[:name] = "actv_ind" if opt[:name].nil?
|
195
|
+
opt[:default] = "Y" if opt[:default].nil?
|
196
|
+
opt[:valid_values] = /^(Y|N)$/i if opt[:valid_values].nil?
|
197
|
+
return Rsmart::ETL::parse_flag str, opt
|
198
|
+
end
|
199
|
+
|
200
|
+
# Designed specifically for actv_ind, but could be used on *any*
|
201
|
+
# fields that matches /^(Y|N)$/i.
|
202
|
+
def self.parse_actv_ind!(row, insert_str, values_str, opt={})
|
203
|
+
# `ACTV_IND` varchar(1) COLLATE utf8_bin DEFAULT 'Y',
|
204
|
+
opt[:name] = "actv_ind" if opt[:name].nil?
|
205
|
+
actv_ind = parse_actv_ind row[ Rsmart::ETL::to_symbol( opt[:name] ) ]
|
206
|
+
Rsmart::ETL::mutate_sql_stmt! insert_str, opt[:name], values_str, actv_ind
|
207
|
+
end
|
208
|
+
|
190
209
|
end
|
@@ -342,7 +342,7 @@ RSpec.describe "Rsmart::ETL" do
|
|
342
342
|
it "Modifies the insert_str and values_str based on a CSV::Row match" do
|
343
343
|
insert_str = ""; values_str = "";
|
344
344
|
row = CSV::Row.new(['actv_ind'.to_sym], ['Y'], true)
|
345
|
-
|
345
|
+
GRM.parse_actv_ind!(row, insert_str, values_str)
|
346
346
|
expect(insert_str).to eq("ACTV_IND,")
|
347
347
|
expect(values_str).to eq("'Y',")
|
348
348
|
end
|
@@ -350,7 +350,7 @@ RSpec.describe "Rsmart::ETL" do
|
|
350
350
|
it "allows for lowercase input Strings" do
|
351
351
|
insert_str = ""; values_str = "";
|
352
352
|
row = CSV::Row.new(['actv_ind'.to_sym], ['n'], true)
|
353
|
-
|
353
|
+
GRM.parse_actv_ind!(row, insert_str, values_str)
|
354
354
|
expect(insert_str).to eq("ACTV_IND,")
|
355
355
|
expect(values_str).to eq("'N',")
|
356
356
|
end
|
@@ -358,12 +358,12 @@ RSpec.describe "Rsmart::ETL" do
|
|
358
358
|
it "Returns a default value of 'Y' and does not raise an TextParseError if nil or empty" do
|
359
359
|
insert_str = ""; values_str = "";
|
360
360
|
row = CSV::Row.new(['actv_ind'.to_sym], [nil], true)
|
361
|
-
expect {
|
361
|
+
expect { GRM.parse_actv_ind!(row, insert_str, values_str) }.not_to raise_error
|
362
362
|
expect(insert_str).to eq("ACTV_IND,")
|
363
363
|
expect(values_str).to eq("'Y',")
|
364
364
|
insert_str = ""; values_str = "";
|
365
365
|
row = CSV::Row.new(['actv_ind'.to_sym], [''], true)
|
366
|
-
expect {
|
366
|
+
expect { GRM.parse_actv_ind!(row, insert_str, values_str) }.not_to raise_error
|
367
367
|
expect(insert_str).to eq("ACTV_IND,")
|
368
368
|
expect(values_str).to eq("'Y',")
|
369
369
|
end
|
@@ -371,13 +371,13 @@ RSpec.describe "Rsmart::ETL" do
|
|
371
371
|
it "Raises an TextParseError if not a valid 'Y/N' value" do
|
372
372
|
insert_str = ""; values_str = "";
|
373
373
|
row = CSV::Row.new(['actv_ind'.to_sym], ["Q"], true)
|
374
|
-
expect {
|
374
|
+
expect { GRM.parse_actv_ind!(row, insert_str, values_str) }.to raise_error(TextParseError)
|
375
375
|
end
|
376
376
|
|
377
377
|
it "Raises an TextParseError if length exceeds 1 characters" do
|
378
378
|
insert_str = ""; values_str = "";
|
379
379
|
row = CSV::Row.new(['actv_ind'.to_sym], ["x" * 2], true)
|
380
|
-
expect {
|
380
|
+
expect { GRM.parse_actv_ind!(row, insert_str, values_str) }.to raise_error(TextParseError)
|
381
381
|
end
|
382
382
|
end
|
383
383
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsmart_toolbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.6'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lance Speelmon
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
sKRWzEtHFamxQaIspOja5O4oQKiCbWa90fEuIoCtwyy1rQtL9VKoDTs4vZASXNuc
|
31
31
|
F/lEyekXSjN36uTtlt4LkKLn/k7k5gRbt4+C9Q==
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2014-08-
|
33
|
+
date: 2014-08-18 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: builder
|
metadata.gz.sig
CHANGED
Binary file
|