bread_calculator 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -13
- data/bin/bread-calc +13 -9
- data/bread_calculator.gemspec +2 -2
- data/lib/bread_calculator.rb +153 -51
- data/spec/bread_calculator_spec.rb +14 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53aef8e8a052ec183a4f4121445c1daa1d15319b
|
4
|
+
data.tar.gz: 2c9b6a67fd14f71f0a3cddbfe2e73aa028dbbe9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72f6258f4ed7b8884e85af325a4c1e5161a433be5e5bb460e80c7530e329aca0e778f143d4becd26059fbc64f08bb45e97001b0c227684734bac1f4427f171bc
|
7
|
+
data.tar.gz: ed81a8f9cff34616d3c2c4199ebaea6b97b2ae44d23441a3bc478effbac1183e4c5e0b4d51a5ce0c95c7bfc059663a3395d7c732536042b9a4c6138b83eb1d8b
|
data/README.md
CHANGED
@@ -98,22 +98,30 @@ can by scaled up or down.</p>
|
|
98
98
|
|
99
99
|
|
100
100
|
<p style="margin-left:11%; margin-top: 1em"><b>--help</b>
|
101
|
-
|
101
|
+
Print a brief usage message.</p>
|
102
102
|
|
103
103
|
|
104
104
|
<p style="margin-left:11%; margin-top: 1em"><b>--summary</b>
|
105
|
-
|
105
|
+
Print all baker’s percentages of the recipe.
|
106
|
+
Over-rides <b>--scale-by</b></p>
|
106
107
|
|
107
108
|
<p style="margin-left:11%; margin-top: 1em"><b>--html</b>
|
108
|
-
|
109
|
+
Print recipe as html. Over-rides <b>--weight</b> or
|
110
|
+
<b>--to.</b></p>
|
109
111
|
|
110
112
|
|
111
113
|
<p style="margin-left:11%; margin-top: 1em"><b>--weight</b>
|
112
|
-
|
114
|
+
Print the weight of the recipe. Over-rides <b>--html</b> or
|
115
|
+
<b>--to.</b></p>
|
116
|
+
|
117
|
+
<p style="margin-left:11%; margin-top: 1em"><b>--to
|
118
|
+
WEIGHT</b> Regenerate the recipe or summary to <b>WEIGHT</b>
|
119
|
+
total weight. Over-rides <b>--html</b> or
|
120
|
+
<b>--weight.</b></p>
|
113
121
|
|
114
122
|
<p style="margin-left:11%; margin-top: 1em"><b>--scale-by
|
115
|
-
FACTOR
|
116
|
-
FACTOR</p>
|
123
|
+
FACTOR.</b> Regenerate the recipe, scaling up or down by
|
124
|
+
<b>FACTOR</b> Over-rides <b>--summary.</b></p>
|
117
125
|
|
118
126
|
<h2>EXAMPLES
|
119
127
|
<a name="EXAMPLES"></a>
|
@@ -121,7 +129,11 @@ FACTOR</p>
|
|
121
129
|
|
122
130
|
|
123
131
|
<p style="margin-left:11%; margin-top: 1em"><b>bread-calc
|
124
|
-
--summary sample.recipe</b
|
132
|
+
--summary sample.recipe</b> summarize a recipe</p>
|
133
|
+
|
134
|
+
<p style="margin-left:11%; margin-top: 1em"><b>bread-calc
|
135
|
+
--scale-by .5 sample.recipe | bread-calc --html
|
136
|
+
>sample.html</b> halve a recipe and render as html</p>
|
125
137
|
|
126
138
|
<h2>FORMATS
|
127
139
|
<a name="FORMATS"></a>
|
@@ -129,7 +141,7 @@ FACTOR</p>
|
|
129
141
|
|
130
142
|
|
131
143
|
<p style="margin-left:11%; margin-top: 1em">The recipe
|
132
|
-
format consists of a metadata prelude
|
144
|
+
format consists of a metadata prelude followed by steps.</p>
|
133
145
|
|
134
146
|
<p style="margin-left:11%; margin-top: 1em">In prelude
|
135
147
|
lines, anything before a colon is considered to be the name
|
@@ -152,14 +164,14 @@ itself.</p>
|
|
152
164
|
|
153
165
|
|
154
166
|
<p style="margin-left:11%; margin-top: 1em"><b>bread-calc</b>
|
155
|
-
|
156
|
-
always force it by including one of the words
|
167
|
+
makes a crude attempt to guess at the type of ingredient,
|
168
|
+
but you can always force it by including one of the words
|
157
169
|
’flour’, ’liquid’, or
|
158
170
|
’additive’ in the line.</p>
|
159
171
|
|
160
172
|
<p style="margin-left:11%; margin-top: 1em">Here is a brief
|
161
|
-
example (note that
|
162
|
-
|
173
|
+
example (note that if you are reading this on github, you
|
174
|
+
won’t see the indenting):</p>
|
163
175
|
|
164
176
|
<p style="margin-left:17%; margin-top: 1em">name: imaginary
|
165
177
|
bread <br>
|
@@ -195,7 +207,7 @@ cheerfully assumed that all units are grams.</p>
|
|
195
207
|
|
196
208
|
<p style="margin-left:11%; margin-top: 1em">It is undefined
|
197
209
|
how ’liquid flour additive’ is parsed, but
|
198
|
-
don’t expect anything
|
210
|
+
don’t expect anything sensible.</p>
|
199
211
|
|
200
212
|
<h2>LICENSE
|
201
213
|
<a name="LICENSE"></a>
|
data/bin/bread-calc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'bread_calculator'
|
4
3
|
#require "#{File.dirname(__FILE__)}/../lib/bread_calculator"
|
4
|
+
require 'bread_calculator'
|
5
5
|
|
6
6
|
def htm_header
|
7
7
|
puts '<head>'
|
@@ -17,29 +17,31 @@ where OPTIONS are any of:
|
|
17
17
|
--summary
|
18
18
|
--html
|
19
19
|
--weight
|
20
|
+
--recipe
|
20
21
|
--scale-by FACTOR
|
21
22
|
|
22
23
|
Install the man page, or go to
|
23
24
|
|
24
25
|
https://github.com/nbirnel/bread-calculator
|
25
26
|
|
26
|
-
for more detailed information.
|
27
|
+
for more detailed and up-to-date information.
|
27
28
|
EOF
|
28
29
|
|
29
30
|
exit status
|
30
31
|
|
31
32
|
end
|
32
33
|
|
33
|
-
@get = 'r'
|
34
34
|
@help = nil
|
35
|
+
@opt = ['r']
|
35
36
|
|
36
37
|
loop { case ARGV[0]
|
37
38
|
when /--help/ then @help = 'help' ; ARGV.shift; break
|
38
|
-
when /--summary/ then @get = 'r.summary'; ARGV.shift
|
39
|
-
when /--html/ then @get = 'r.to_html'; ARGV.shift
|
40
|
-
when /--weight/ then @get = 'r.weight'; ARGV.shift
|
41
39
|
#.to_f protects against 'no .<digit> floating literal anymore' for .33
|
42
|
-
when /--scale-by/ then ARGV.shift; @
|
40
|
+
when /--scale-by/ then ARGV.shift; @opt[1] = "scale_by(#{ARGV.shift.to_f})"
|
41
|
+
when /--summary/ then @opt[1] = 'summary'; ARGV.shift
|
42
|
+
when /--html/ then @opt[2] = 'to_html'; ARGV.shift
|
43
|
+
when /--weight/ then @opt[2] = 'weight'; ARGV.shift
|
44
|
+
when /--to/ then ARGV.shift; @opt[2] = "recipe(#{ARGV.shift.to_f})"
|
43
45
|
when /--/ then ARGV.shift; break
|
44
46
|
when /^-/ then help 1
|
45
47
|
else break
|
@@ -47,8 +49,10 @@ end; }
|
|
47
49
|
|
48
50
|
help if @help
|
49
51
|
|
52
|
+
@method_chain = @opt.select{|e| e if e}.join('.')
|
53
|
+
|
50
54
|
parser = BreadCalculator::Parser.new
|
51
55
|
r = parser.parse ARGF.file
|
52
|
-
htm_header if @
|
53
|
-
puts eval("#{@
|
56
|
+
htm_header if @method_chain.include? 'to_html'
|
57
|
+
puts eval("#{@method_chain}")
|
54
58
|
|
data/bread_calculator.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'bread_calculator'
|
3
|
-
s.version = '0.
|
4
|
-
s.date = '2014-03-
|
3
|
+
s.version = '0.4.0'
|
4
|
+
s.date = '2014-03-13'
|
5
5
|
s.summary = "calculate baker's percentages"
|
6
6
|
s.description = "a gem and command-line wrapper to generate baker's
|
7
7
|
percentages from a bread recipe"
|
data/lib/bread_calculator.rb
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
##
|
2
|
+
# round +number+ depending on it's magnitude
|
3
|
+
|
4
|
+
def human_round number, base_precision = 0
|
5
|
+
#FIXME there is an algorithm for this. What is it?
|
6
|
+
precision = base_precision
|
7
|
+
if number < 10
|
8
|
+
precision = base_precision + 1
|
9
|
+
end
|
10
|
+
if number < 1
|
11
|
+
precision = base_precision + 2
|
12
|
+
end
|
13
|
+
f_number = sprintf "%.#{precision}f", number
|
14
|
+
end
|
15
|
+
|
1
16
|
##
|
2
17
|
# Classes for manipulating bread recipes and baker's percentages
|
3
18
|
|
@@ -5,6 +20,9 @@ module BreadCalculator
|
|
5
20
|
|
6
21
|
require 'cgi'
|
7
22
|
|
23
|
+
##
|
24
|
+
# Make a reasonably precise representation of +number+
|
25
|
+
|
8
26
|
##
|
9
27
|
# This class represents an ingredient in a Recipe
|
10
28
|
|
@@ -19,7 +37,7 @@ module BreadCalculator
|
|
19
37
|
# +:liquids+, or +:additives+.
|
20
38
|
|
21
39
|
def initialize name, info={}
|
22
|
-
|
40
|
+
#@units = 'grams'
|
23
41
|
@name = name
|
24
42
|
@info = info
|
25
43
|
info.each do |k,v|
|
@@ -30,7 +48,7 @@ module BreadCalculator
|
|
30
48
|
##
|
31
49
|
# Returns a new Ingredient, scaled from current instance by +ratio+
|
32
50
|
|
33
|
-
def scale_by ratio
|
51
|
+
def scale_by ratio, units=self.units
|
34
52
|
scaled = Hash.new
|
35
53
|
self.info.each do |k, v|
|
36
54
|
scaled[k] = v
|
@@ -38,21 +56,30 @@ module BreadCalculator
|
|
38
56
|
end
|
39
57
|
Ingredient.new(self.name, scaled)
|
40
58
|
end
|
59
|
+
|
60
|
+
#FIXME refactor scale_by and as_bp
|
61
|
+
|
62
|
+
##
|
63
|
+
# Returns a new unitless Ingredient as a baker's percentage of +bp_100+
|
64
|
+
|
65
|
+
def as_bp bp_100
|
66
|
+
info = self.info.reject{|k,v| k == :units}
|
67
|
+
|
68
|
+
scaled = Hash.new
|
69
|
+
info.each do |k, v|
|
70
|
+
scaled[k] = v
|
71
|
+
scaled[k] = v / bp_100.to_f if k == :quantity
|
72
|
+
end
|
73
|
+
Ingredient.new(self.name, scaled)
|
74
|
+
end
|
41
75
|
|
42
76
|
##
|
43
77
|
# Print a nice text version of Ingredient
|
44
78
|
|
45
|
-
def to_s
|
79
|
+
def to_s summary=nil
|
80
|
+
q = summary ? "#{human_round(@quantity*100).to_s}%" : human_round(@quantity)
|
46
81
|
#FIXME check for existance
|
47
|
-
|
48
|
-
if @quantity < 10
|
49
|
-
precision = 1
|
50
|
-
end
|
51
|
-
if @quantity < 1
|
52
|
-
precision = 2
|
53
|
-
end
|
54
|
-
f_quantity = sprintf "%.#{precision}f", @quantity
|
55
|
-
"\t#{f_quantity} #{@units} #{@name}\n"
|
82
|
+
"\t#{q} #{@units} #{@name}\n"
|
56
83
|
end
|
57
84
|
|
58
85
|
##
|
@@ -87,6 +114,7 @@ module BreadCalculator
|
|
87
114
|
|
88
115
|
##
|
89
116
|
# Sets +Step.techniques+ to +args+, and defines +Step.ingredients+
|
117
|
+
|
90
118
|
def techniques= args
|
91
119
|
@techniques = args
|
92
120
|
@ingredients = args.select{|arg| arg.is_a? Ingredient}
|
@@ -95,10 +123,10 @@ module BreadCalculator
|
|
95
123
|
##
|
96
124
|
# Print a nice text version of Step
|
97
125
|
|
98
|
-
def to_s
|
126
|
+
def to_s summary=nil
|
99
127
|
out = ''
|
100
128
|
self.techniques.each do |t|
|
101
|
-
tmp = t.is_a?(Ingredient) ? t.to_s : "#{t.chomp}\n"
|
129
|
+
tmp = t.is_a?(Ingredient) ? t.to_s(summary) : "#{t.chomp}\n"
|
102
130
|
out << tmp
|
103
131
|
end
|
104
132
|
out << "\n"
|
@@ -117,10 +145,19 @@ module BreadCalculator
|
|
117
145
|
out << "\n</p>\n"
|
118
146
|
out
|
119
147
|
end
|
148
|
+
|
120
149
|
end
|
121
150
|
|
122
151
|
##
|
123
152
|
# This class represents a recipe.
|
153
|
+
#
|
154
|
+
# Runtime-generated methods:
|
155
|
+
#
|
156
|
+
# total_flours
|
157
|
+
# total_liquids
|
158
|
+
# total_additives
|
159
|
+
#
|
160
|
+
# return totals of their respective types
|
124
161
|
|
125
162
|
class Recipe
|
126
163
|
attr_reader :steps, :metadata
|
@@ -132,7 +169,7 @@ module BreadCalculator
|
|
132
169
|
# Other likely keys are:
|
133
170
|
# <tt>:prep_time, :total_time, :notes, :history, :serves, :makes,
|
134
171
|
# :attribution</tt>.
|
135
|
-
|
172
|
+
|
136
173
|
def initialize metadata, steps
|
137
174
|
@metadata = metadata
|
138
175
|
@steps = steps
|
@@ -162,6 +199,7 @@ module BreadCalculator
|
|
162
199
|
#FIXME make this a method_missing so we can add new types on the fly
|
163
200
|
#RENÉE - 'end.' is weird or no?
|
164
201
|
#FIXME how do I get this into rdoc?
|
202
|
+
|
165
203
|
[:flours, :liquids, :additives].each do |s|
|
166
204
|
define_method("total_#{s}") do
|
167
205
|
instance_variable_get("@ingredients").select{|i| i.type == s}.map do |i|
|
@@ -192,7 +230,7 @@ module BreadCalculator
|
|
192
230
|
|
193
231
|
def scale_by ratio
|
194
232
|
new_steps = self.steps.map do |s|
|
195
|
-
step_args =
|
233
|
+
step_args = s.techniques.map do |t|
|
196
234
|
t.is_a?(Ingredient) ? t.scale_by(ratio) : t
|
197
235
|
end
|
198
236
|
Step.new step_args
|
@@ -205,16 +243,19 @@ module BreadCalculator
|
|
205
243
|
# Returns a Summary
|
206
244
|
|
207
245
|
def summary
|
208
|
-
|
246
|
+
new_meta = self.metadata
|
209
247
|
[:flours, :liquids, :additives].each do |s|
|
210
|
-
|
248
|
+
new_meta["total_#{s}"] = eval "self.bakers_percent self.total_#{s}"
|
211
249
|
end
|
212
250
|
|
213
|
-
|
214
|
-
|
215
|
-
|
251
|
+
new_steps = self.steps.map do |s|
|
252
|
+
step_args = s.techniques.map do |t|
|
253
|
+
t.is_a?(Ingredient) ? t.as_bp(self.bakers_percent_100) : t
|
254
|
+
end
|
255
|
+
Step.new step_args
|
216
256
|
end
|
217
|
-
|
257
|
+
|
258
|
+
Summary.new new_meta, new_steps
|
218
259
|
end
|
219
260
|
|
220
261
|
##
|
@@ -242,6 +283,67 @@ module BreadCalculator
|
|
242
283
|
|
243
284
|
end
|
244
285
|
|
286
|
+
##
|
287
|
+
# This class represents a summary of a Recipe - like a Recipe, but:
|
288
|
+
#
|
289
|
+
# Ingredients will be unitless
|
290
|
+
# and the quantities expressed in baker's percentages,
|
291
|
+
#
|
292
|
+
# Metadata will include baker's percentages of
|
293
|
+
# flours, liquids, and additives.
|
294
|
+
|
295
|
+
class Summary < Recipe
|
296
|
+
|
297
|
+
def initialize metadata, steps
|
298
|
+
super
|
299
|
+
end
|
300
|
+
|
301
|
+
def weight
|
302
|
+
nil
|
303
|
+
end
|
304
|
+
|
305
|
+
def summary
|
306
|
+
self
|
307
|
+
end
|
308
|
+
|
309
|
+
def to_s
|
310
|
+
#FIXME this should be calling super somehow
|
311
|
+
out = ''
|
312
|
+
self.metadata.each do |k,v|
|
313
|
+
nv = k.to_s =~ /^total_/ ? "#{human_round(v*100).to_s}%" : v
|
314
|
+
out << "#{k}: #{nv}\n"
|
315
|
+
end
|
316
|
+
out << "--------------------\n"
|
317
|
+
self.steps.each{|s| out << s.to_s(:summary)}
|
318
|
+
out
|
319
|
+
end
|
320
|
+
|
321
|
+
def to_html
|
322
|
+
#FIXME obviously inadequate
|
323
|
+
super
|
324
|
+
end
|
325
|
+
|
326
|
+
def recipe weight, units='grams'
|
327
|
+
|
328
|
+
new_metadata = self.metadata.reject{|k,v| k.to_s =~ /^total_/}
|
329
|
+
|
330
|
+
totals = self.metadata.select{|k,v| k.to_s =~ /^total_/}
|
331
|
+
all_totals = totals.values.inject(:+).to_f
|
332
|
+
new_bp_100 = weight / all_totals
|
333
|
+
|
334
|
+
new_steps = self.steps.map do |s|
|
335
|
+
step_args = s.techniques.map do |t|
|
336
|
+
t.is_a?(Ingredient) ? t.scale_by(new_bp_100, units) : t
|
337
|
+
end
|
338
|
+
Step.new step_args
|
339
|
+
end
|
340
|
+
|
341
|
+
Recipe.new new_metadata, new_steps
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
end
|
346
|
+
|
245
347
|
##
|
246
348
|
# This class converts a nearly free-form text file to a Recipe
|
247
349
|
|
@@ -263,7 +365,35 @@ module BreadCalculator
|
|
263
365
|
##
|
264
366
|
# Parse text from IO object +input+. It is the caller's responsibility to
|
265
367
|
# open and close the +input+ correctly.
|
266
|
-
|
368
|
+
#
|
369
|
+
# text recipes consist of a metadata prelude followed by steps.
|
370
|
+
#
|
371
|
+
# In prelude lines,
|
372
|
+
# anything before a colon is considered to be the name of a metadata field;
|
373
|
+
# anything after the colon is a value to populate.
|
374
|
+
# Lines without colons are continuations of the 'notes' field.
|
375
|
+
# I suggest having at least a 'name' field.
|
376
|
+
#
|
377
|
+
# A line starting with a hyphen ends the prelude and starts the first step.
|
378
|
+
#
|
379
|
+
# Each step is delimited by one or more blank lines.
|
380
|
+
#
|
381
|
+
# Any line in a step starting with a space or a blank is an ingredient,
|
382
|
+
# consisting of quantity, units, and the ingredient itself.
|
383
|
+
#
|
384
|
+
# A brief sample:
|
385
|
+
#
|
386
|
+
# name: imaginary bread
|
387
|
+
# notes: This is a silly fake bread recipe
|
388
|
+
# makes: 1 bad loaf
|
389
|
+
# This line will become part of the notes
|
390
|
+
# ---------------------
|
391
|
+
# Mix:
|
392
|
+
# 500 g flour
|
393
|
+
# 300 g water
|
394
|
+
#
|
395
|
+
# Bake at 375°
|
396
|
+
|
267
397
|
def parse input
|
268
398
|
|
269
399
|
while line = input.gets
|
@@ -337,32 +467,4 @@ module BreadCalculator
|
|
337
467
|
|
338
468
|
end
|
339
469
|
|
340
|
-
##
|
341
|
-
# This class represents a summary of a Recipe - no Steps or units, just
|
342
|
-
# baker's percentages of each ingredient, and a prelude of baker's
|
343
|
-
# percentages for flours, liquids, and additives.
|
344
|
-
|
345
|
-
class Summary
|
346
|
-
attr_accessor :types, :ingredients
|
347
|
-
|
348
|
-
##
|
349
|
-
# Create a new Summary of +types+ and +ingredients+
|
350
|
-
|
351
|
-
def initialize types, ingredients
|
352
|
-
@types = types
|
353
|
-
@ingredients = ingredients
|
354
|
-
end
|
355
|
-
|
356
|
-
##
|
357
|
-
# Print it nicely
|
358
|
-
|
359
|
-
def to_s
|
360
|
-
out = ''
|
361
|
-
self.types.each{|k,v| out << "#{k}: #{v}\n"}
|
362
|
-
out << "--------------------\n"
|
363
|
-
self.ingredients.each{|k,v| out << "#{k}: #{v}\n"}
|
364
|
-
out
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
470
|
end
|
@@ -17,6 +17,7 @@ describe BreadCalculator do
|
|
17
17
|
@bake = BreadCalculator::Step.new 'Form a loaf, rise for 2 hours, Bake at 375° for 45 minutes.'
|
18
18
|
@meta = {:notes => 'nice sandwich bread'}
|
19
19
|
@recipe = BreadCalculator::Recipe.new @meta, [@proof, @wet, @dry, @mix, @bake]
|
20
|
+
@summary = @recipe.summary
|
20
21
|
end
|
21
22
|
|
22
23
|
describe BreadCalculator::Ingredient do
|
@@ -49,7 +50,7 @@ describe BreadCalculator do
|
|
49
50
|
end
|
50
51
|
|
51
52
|
it 'generates a baker\'s percentage summary' do
|
52
|
-
@
|
53
|
+
@summary.is_a?(BreadCalculator::Summary).should be_true
|
53
54
|
end
|
54
55
|
|
55
56
|
it 'scales' do
|
@@ -68,6 +69,18 @@ describe BreadCalculator do
|
|
68
69
|
|
69
70
|
end
|
70
71
|
|
72
|
+
describe BreadCalculator::Summary do
|
73
|
+
before do
|
74
|
+
@new_recipe = @summary.recipe(1000, 'g')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'generates a Recipe' do
|
78
|
+
@new_recipe.is_a?(BreadCalculator::Recipe).should be_true
|
79
|
+
@new_recipe.weight.should == 1000
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
71
84
|
describe BreadCalculator::Parser do
|
72
85
|
before do
|
73
86
|
@parser = BreadCalculator::Parser.new
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bread_calculator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Birnel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
a gem and command-line wrapper to generate baker's
|