pivotal-erector 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +10 -5
- data/VERSION.yml +1 -1
- data/bin/erector +3 -1
- data/lib/erector/erect.rb +4 -2
- data/lib/erector/erected.rb +14 -4
- data/lib/erector/mixin.rb +7 -0
- data/lib/erector/rhtml.treetop +48 -11
- data/lib/erector/widget.rb +146 -113
- data/lib/erector.rb +1 -0
- data/spec/erect/erect_rails_spec.rb +62 -0
- data/spec/erect/erect_spec.rb +165 -0
- data/spec/erect/erected_spec.rb +93 -0
- data/spec/erect/rhtml_parser_spec.rb +351 -0
- data/spec/erector/mixin_spec.rb +54 -0
- data/spec/erector/widget_spec.rb +38 -0
- metadata +14 -2
data/lib/erector/widget.rb
CHANGED
@@ -2,45 +2,49 @@ module Erector
|
|
2
2
|
|
3
3
|
# A Widget is the center of the Erector universe.
|
4
4
|
#
|
5
|
-
# To create a widget, extend Erector::Widget and implement
|
6
|
-
#
|
7
|
-
# tags.
|
8
|
-
#
|
9
|
-
# You can also define a widget on the fly by passing a block to +new+. This
|
10
|
-
# +content+ method is called.
|
5
|
+
# To create a widget, extend Erector::Widget and implement the +content+
|
6
|
+
# method. Inside this method you may call any of the tag methods like +span+
|
7
|
+
# or +p+ to emit HTML/XML tags.
|
8
|
+
#
|
9
|
+
# You can also define a widget on the fly by passing a block to +new+. This
|
10
|
+
# block will get executed when the widget's +content+ method is called.
|
11
11
|
#
|
12
|
-
# To render a widget from the outside, instantiate it and call its +to_s+
|
12
|
+
# To render a widget from the outside, instantiate it and call its +to_s+
|
13
|
+
# method.
|
13
14
|
#
|
14
|
-
# A widget's +new+ method optionally accepts an options hash. Entries in
|
15
|
-
# variables, and +attr_reader+ accessors
|
15
|
+
# A widget's +new+ method optionally accepts an options hash. Entries in
|
16
|
+
# this hash are converted to instance variables, and +attr_reader+ accessors
|
17
|
+
# are defined for each.
|
16
18
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# helpers of the enclosing class.
|
27
|
-
#
|
28
|
-
# In this documentation we've tried to keep the distinction clear between
|
29
|
-
# *
|
30
|
-
#
|
19
|
+
# You can add runtime input checking via the +needs+ macro. See #needs.
|
20
|
+
# This mechanism is meant to ameliorate development-time confusion about
|
21
|
+
# exactly what parameters are supported by a given widget, avoiding
|
22
|
+
# confusing runtime NilClass errors.
|
23
|
+
#
|
24
|
+
# To call one widget from another, inside the parent widget's +content+
|
25
|
+
# method, instantiate the child widget and call the +widget+ method. This
|
26
|
+
# assures that the same output stream is used, which gives better
|
27
|
+
# performance than using +capture+ or +to_s+. It also preserves the
|
28
|
+
# indentation and helpers of the enclosing class.
|
29
|
+
#
|
30
|
+
# In this documentation we've tried to keep the distinction clear between
|
31
|
+
# methods that *emit* text and those that *return* text. "Emit" means that
|
32
|
+
# it writes to the output stream; "return" means that it returns a string
|
33
|
+
# like a normal method and leaves it up to the caller to emit that string if
|
34
|
+
# it wants.
|
31
35
|
class Widget
|
32
36
|
class << self
|
33
37
|
def all_tags
|
34
38
|
Erector::Widget.full_tags + Erector::Widget.empty_tags
|
35
39
|
end
|
36
40
|
|
37
|
-
#
|
41
|
+
# Tags which are always self-closing. Click "[Source]" to see the full list.
|
38
42
|
def empty_tags
|
39
43
|
['area', 'base', 'br', 'col', 'frame',
|
40
44
|
'hr', 'img', 'input', 'link', 'meta']
|
41
45
|
end
|
42
46
|
|
43
|
-
#
|
47
|
+
# Tags which can contain other stuff. Click "[Source]" to see the full list.
|
44
48
|
def full_tags
|
45
49
|
[
|
46
50
|
'a', 'abbr', 'acronym', 'address',
|
@@ -81,36 +85,37 @@ module Erector
|
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
84
|
-
# Class method by which widget classes can declare that they need certain
|
85
|
-
# If needed parameters are not passed in to #new, then an
|
86
|
-
# (with a hopefully useful message about which
|
87
|
-
#
|
88
|
-
# a parameter called '
|
89
|
-
#
|
88
|
+
# Class method by which widget classes can declare that they need certain
|
89
|
+
# parameters. If needed parameters are not passed in to #new, then an
|
90
|
+
# exception will be thrown (with a hopefully useful message about which
|
91
|
+
# parameters are missing). This is intended to catch silly bugs like
|
92
|
+
# passing in a parameter called 'name' to a widget that expects a
|
93
|
+
# parameter called 'title'. Every variable declared in 'needs' will get an
|
94
|
+
# attr_reader accessor declared for it.
|
90
95
|
#
|
91
|
-
# You can also declare default values for parameters using hash syntax.
|
92
|
-
# declarations on multiple lines or on the same line;
|
93
|
-
#
|
94
|
-
# hash parameter).
|
96
|
+
# You can also declare default values for parameters using hash syntax.
|
97
|
+
# You can put #needs declarations on multiple lines or on the same line;
|
98
|
+
# the only caveat is that if there are default values, they all have to be
|
99
|
+
# at the end of the line (so they go into the magic hash parameter).
|
95
100
|
#
|
96
|
-
# If a widget has no #needs declaration then it will accept any
|
97
|
-
# (and make accessors for them) just like
|
98
|
-
# declared.
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
101
|
+
# If a widget has no #needs declaration then it will accept any
|
102
|
+
# combination of parameters (and make accessors for them) just like
|
103
|
+
# normal. In that case there will be no 'attr_reader's declared. If a
|
104
|
+
# widget wants to declare that it takes no parameters, use the special
|
105
|
+
# incantation "needs nil" (and don't declare any other needs, or kittens
|
106
|
+
# will cry).
|
102
107
|
#
|
103
108
|
# Usage:
|
104
109
|
# class FancyForm < Erector::Widget
|
105
110
|
# needs :title, :show_okay => true, :show_cancel => false
|
106
111
|
# ...
|
107
112
|
# end
|
108
|
-
#
|
109
|
-
# That means that
|
113
|
+
#
|
114
|
+
# That means that
|
110
115
|
# FancyForm.new(:title => 'Login')
|
111
|
-
# will succeed, as will
|
116
|
+
# will succeed, as will
|
112
117
|
# FancyForm.new(:title => 'Login', :show_cancel => true)
|
113
|
-
# but
|
118
|
+
# but
|
114
119
|
# FancyForm.new(:name => 'Login')
|
115
120
|
# will fail.
|
116
121
|
#
|
@@ -237,25 +242,38 @@ module Erector
|
|
237
242
|
to_s(:prettyprint => true)
|
238
243
|
end
|
239
244
|
|
240
|
-
# Entry point for rendering a widget (and all its children). This method
|
241
|
-
# calls this widget's #content
|
245
|
+
# Entry point for rendering a widget (and all its children). This method
|
246
|
+
# creates a new output string (if necessary), calls this widget's #content
|
247
|
+
# method and returns the string.
|
242
248
|
#
|
243
249
|
# Options:
|
244
250
|
# output:: the string to output to. Default: a new empty string
|
245
|
-
# prettyprint:: whether Erector should add newlines and indentation.
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
251
|
-
#
|
252
|
-
#
|
251
|
+
# prettyprint:: whether Erector should add newlines and indentation.
|
252
|
+
# Default: the value of prettyprint_default (which is false
|
253
|
+
# by default).
|
254
|
+
# indentation:: the amount of spaces to indent. Ignored unless prettyprint
|
255
|
+
# is true.
|
256
|
+
# helpers:: a helpers object containing utility methods. Usually this is a
|
257
|
+
# Rails view object.
|
258
|
+
# content_method_name:: in case you want to call a method other than
|
259
|
+
# #content, pass its name in here.
|
253
260
|
def to_s(options = {}, &blk)
|
254
|
-
|
255
261
|
raise "Erector::Widget#to_s now takes an options hash, not a symbol. Try calling \"to_s(:content_method_name=> :#{options})\"" if options.is_a? Symbol
|
256
|
-
|
262
|
+
_render(options, &blk).to_s
|
263
|
+
end
|
264
|
+
|
265
|
+
# Entry point for rendering a widget (and all its children). Same as #to_s
|
266
|
+
# only it returns an array, for theoretical performance improvements when using a
|
267
|
+
# Rack server (like Sinatra or Rails Metal).
|
268
|
+
#
|
269
|
+
# # Options: see #to_s
|
270
|
+
def to_a(options = {}, &blk)
|
271
|
+
_render(options, &blk).to_a
|
272
|
+
end
|
273
|
+
|
274
|
+
def _render(options = {}, &blk)
|
257
275
|
options = {
|
258
|
-
:output => "",
|
276
|
+
:output => "", # "" is apparently faster than [] in a long-running process
|
259
277
|
:prettyprint => prettyprint_default,
|
260
278
|
:indentation => 0,
|
261
279
|
:helpers => nil,
|
@@ -263,24 +281,29 @@ module Erector
|
|
263
281
|
}.merge(options)
|
264
282
|
context(options[:output], options[:prettyprint], options[:indentation], options[:helpers]) do
|
265
283
|
send(options[:content_method_name], &blk)
|
266
|
-
output
|
284
|
+
output
|
267
285
|
end
|
268
286
|
end
|
269
287
|
|
270
288
|
alias_method :inspect, :to_s
|
271
289
|
|
272
|
-
# Template method which must be overridden by all widget subclasses.
|
273
|
-
# #element methods which emit HTML
|
290
|
+
# Template method which must be overridden by all widget subclasses.
|
291
|
+
# Inside this method you call the magic #element methods which emit HTML
|
292
|
+
# and text to the output string. If you call "super" (or don't override
|
293
|
+
# +content+) then your widget will render any block that was passed into
|
294
|
+
# its constructor (in the current instance context so it can get access
|
295
|
+
# to parent widget methods via method_missing).
|
274
296
|
def content
|
275
297
|
if @block
|
276
298
|
instance_eval(&@block)
|
277
299
|
end
|
278
300
|
end
|
279
301
|
|
280
|
-
# To call one widget from another, inside the parent widget's +content+
|
281
|
-
#
|
282
|
-
#
|
283
|
-
#
|
302
|
+
# To call one widget from another, inside the parent widget's +content+
|
303
|
+
# method, instantiate the child widget and call its +write_via+ method,
|
304
|
+
# passing in +self+. This assures that the same output string is used,
|
305
|
+
# which gives better performance than using +capture+ or +to_s+. You can
|
306
|
+
# also use the +widget+ method.
|
284
307
|
def write_via(parent)
|
285
308
|
@parent = parent
|
286
309
|
context(parent.output, parent.prettyprint, parent.indentation, parent.helpers) do
|
@@ -288,13 +311,14 @@ module Erector
|
|
288
311
|
end
|
289
312
|
end
|
290
313
|
|
291
|
-
# Emits a (nested) widget onto the current widget's output stream. Accepts
|
292
|
-
# a class or an instance. If the first argument is a class, then
|
293
|
-
# is a hash used to populate its instance variables.
|
294
|
-
# instance then the hash must be unspecified
|
314
|
+
# Emits a (nested) widget onto the current widget's output stream. Accepts
|
315
|
+
# either a class or an instance. If the first argument is a class, then
|
316
|
+
# the second argument is a hash used to populate its instance variables.
|
317
|
+
# If the first argument is an instance then the hash must be unspecified
|
318
|
+
# (or empty).
|
295
319
|
#
|
296
|
-
# The sub-widget will have access to the methods of the parent class, via
|
297
|
-
# magic and a "parent" pointer.
|
320
|
+
# The sub-widget will have access to the methods of the parent class, via
|
321
|
+
# some method_missing magic and a "parent" pointer.
|
298
322
|
def widget(target, assigns={}, &block)
|
299
323
|
child = if target.is_a? Class
|
300
324
|
target.new(assigns, &block)
|
@@ -315,40 +339,46 @@ module Erector
|
|
315
339
|
#-- methods for subclasses to call
|
316
340
|
#++
|
317
341
|
|
318
|
-
# Internal method used to emit an HTML/XML element, including an open tag,
|
319
|
-
# contents (also optional),
|
342
|
+
# Internal method used to emit an HTML/XML element, including an open tag,
|
343
|
+
# attributes (optional, via the default hash), contents (also optional),
|
344
|
+
# and close tag.
|
320
345
|
#
|
321
|
-
# Using the arcane powers of Ruby, there are magic methods that call
|
322
|
-
# HTML tags, like +a+, +body+, +p+, and so
|
323
|
-
#
|
324
|
-
#
|
346
|
+
# Using the arcane powers of Ruby, there are magic methods that call
|
347
|
+
# +element+ for all the standard HTML tags, like +a+, +body+, +p+, and so
|
348
|
+
# forth. Look at the source of #full_tags for the full list.
|
349
|
+
# Unfortunately, this big mojo confuses rdoc, so we can't see each method
|
350
|
+
# in this rdoc page, but trust us, they're there.
|
325
351
|
#
|
326
|
-
# When calling one of these magic methods, put attributes in the default
|
327
|
-
#
|
328
|
-
#
|
329
|
-
#
|
330
|
-
#
|
352
|
+
# When calling one of these magic methods, put attributes in the default
|
353
|
+
# hash. If there is a string parameter, then it is used as the contents.
|
354
|
+
# If there is a block, then it is executed (yielded), and the string
|
355
|
+
# parameter is ignored. The block will usually be in the scope of the
|
356
|
+
# child widget, which means it has access to all the methods of Widget,
|
357
|
+
# which will eventually end up appending text to the +output+ string. See
|
358
|
+
# how elegant it is? Not confusing at all if you don't think about it.
|
331
359
|
#
|
332
360
|
def element(*args, &block)
|
333
361
|
__element__(*args, &block)
|
334
362
|
end
|
335
363
|
|
336
|
-
# Internal method used to emit a self-closing HTML/XML element, including
|
337
|
-
# (passed in via the default hash).
|
338
|
-
#
|
339
|
-
# Using the arcane powers of Ruby, there are magic methods that call
|
340
|
-
# HTML tags, like +img+, +br+, and so
|
341
|
-
#
|
342
|
-
#
|
364
|
+
# Internal method used to emit a self-closing HTML/XML element, including
|
365
|
+
# a tag name and optional attributes (passed in via the default hash).
|
366
|
+
#
|
367
|
+
# Using the arcane powers of Ruby, there are magic methods that call
|
368
|
+
# +empty_element+ for all the standard HTML tags, like +img+, +br+, and so
|
369
|
+
# forth. Look at the source of #empty_tags for the full list.
|
370
|
+
# Unfortunately, this big mojo confuses rdoc, so we can't see each method
|
371
|
+
# in this rdoc page, but trust us, they're there.
|
343
372
|
#
|
344
373
|
def empty_element(*args, &block)
|
345
374
|
__empty_element__(*args, &block)
|
346
375
|
end
|
347
376
|
|
348
|
-
# Returns an HTML-escaped version of its parameter. Leaves the output
|
349
|
-
# the #text method automatically HTML-escapes
|
350
|
-
#
|
351
|
-
#
|
377
|
+
# Returns an HTML-escaped version of its parameter. Leaves the output
|
378
|
+
# string untouched. Note that the #text method automatically HTML-escapes
|
379
|
+
# its parameter, so be careful *not* to do something like text(h("2<4"))
|
380
|
+
# since that will double-escape the less-than sign (you'll get
|
381
|
+
# "2&lt;4" instead of "2<4").
|
352
382
|
def h(content)
|
353
383
|
content.html_escape
|
354
384
|
end
|
@@ -358,20 +388,20 @@ module Erector
|
|
358
388
|
indent_for_open_tag(tag_name)
|
359
389
|
@indentation += SPACES_PER_INDENT
|
360
390
|
|
361
|
-
output
|
391
|
+
output << "<#{tag_name}#{format_attributes(attributes)}>"
|
362
392
|
@at_start_of_line = false
|
363
393
|
end
|
364
394
|
|
365
|
-
# Emits text. If a string is passed in, it will be HTML-escaped.
|
366
|
-
#
|
367
|
-
#
|
368
|
-
#
|
369
|
-
#
|
395
|
+
# Emits text. If a string is passed in, it will be HTML-escaped. If a
|
396
|
+
# widget or the result of calling methods such as raw is passed in, the
|
397
|
+
# HTML will not be HTML-escaped again. If another kind of object is passed
|
398
|
+
# in, the result of calling its to_s method will be treated as a string
|
399
|
+
# would be.
|
370
400
|
def text(value)
|
371
401
|
if value.is_a? Widget
|
372
402
|
widget value
|
373
403
|
else
|
374
|
-
output
|
404
|
+
output <<(value.html_escape)
|
375
405
|
end
|
376
406
|
@at_start_of_line = false
|
377
407
|
nil
|
@@ -410,12 +440,12 @@ module Erector
|
|
410
440
|
end
|
411
441
|
end
|
412
442
|
|
413
|
-
# Emits a close tag, consisting of '<', tag name, and '>'
|
443
|
+
# Emits a close tag, consisting of '<', '/', tag name, and '>'
|
414
444
|
def close_tag(tag_name)
|
415
445
|
@indentation -= SPACES_PER_INDENT
|
416
446
|
indent()
|
417
447
|
|
418
|
-
output
|
448
|
+
output <<("</#{tag_name}>")
|
419
449
|
|
420
450
|
if newliney(tag_name)
|
421
451
|
_newline
|
@@ -438,12 +468,13 @@ module Erector
|
|
438
468
|
|
439
469
|
# Emits an XML instruction, which looks like this: <?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
440
470
|
def instruct(attributes={:version => "1.0", :encoding => "UTF-8"})
|
441
|
-
output
|
471
|
+
output << "<?xml#{format_sorted(sort_for_xml_declaration(attributes))}?>"
|
442
472
|
end
|
443
473
|
|
444
|
-
# Creates a whole new output string, executes the block, then converts the
|
445
|
-
# emits it as raw text. If at all possible
|
446
|
-
#
|
474
|
+
# Creates a whole new output string, executes the block, then converts the
|
475
|
+
# output string to a string and emits it as raw text. If at all possible
|
476
|
+
# you should avoid this method since it hurts performance, and use
|
477
|
+
# +widget+ or +write_via+ instead.
|
447
478
|
def capture(&block)
|
448
479
|
begin
|
449
480
|
original_output = output
|
@@ -475,7 +506,8 @@ module Erector
|
|
475
506
|
)
|
476
507
|
end
|
477
508
|
|
478
|
-
# Emits a javascript block inside a +script+ tag, wrapped in CDATA
|
509
|
+
# Emits a javascript block inside a +script+ tag, wrapped in CDATA
|
510
|
+
# doohickeys like all the cool JS kids do.
|
479
511
|
def javascript(*args, &block)
|
480
512
|
if args.length > 2
|
481
513
|
raise ArgumentError, "Cannot accept more than two arguments"
|
@@ -514,16 +546,17 @@ module Erector
|
|
514
546
|
rawtext "\n"
|
515
547
|
end
|
516
548
|
|
517
|
-
# Convenience method to emit a css file link, which looks like this:
|
549
|
+
# Convenience method to emit a css file link, which looks like this:
|
518
550
|
# <link href="erector.css" rel="stylesheet" type="text/css" />
|
519
|
-
# The parameter is the full contents of the href attribute, including any ".css" extension.
|
551
|
+
# The parameter is the full contents of the href attribute, including any ".css" extension.
|
520
552
|
#
|
521
553
|
# If you want to emit raw CSS inline, use the #style method instead.
|
522
554
|
def css(href)
|
523
555
|
link :rel => 'stylesheet', :type => 'text/css', :href => href
|
524
556
|
end
|
525
557
|
|
526
|
-
# Convenience method to emit an anchor tag whose href and text are the same,
|
558
|
+
# Convenience method to emit an anchor tag whose href and text are the same,
|
559
|
+
# e.g. <a href="http://example.com">http://example.com</a>
|
527
560
|
def url(href)
|
528
561
|
a href, :href => href
|
529
562
|
end
|
@@ -581,7 +614,7 @@ protected
|
|
581
614
|
def __empty_element__(tag_name, attributes={})
|
582
615
|
indent_for_open_tag(tag_name)
|
583
616
|
|
584
|
-
output
|
617
|
+
output << "<#{tag_name}#{format_attributes(attributes)} />"
|
585
618
|
|
586
619
|
if newliney(tag_name)
|
587
620
|
_newline
|
@@ -590,7 +623,7 @@ protected
|
|
590
623
|
|
591
624
|
def _newline
|
592
625
|
return unless @prettyprint
|
593
|
-
output
|
626
|
+
output << "\n"
|
594
627
|
@at_start_of_line = true
|
595
628
|
end
|
596
629
|
|
@@ -604,7 +637,7 @@ protected
|
|
604
637
|
|
605
638
|
def indent()
|
606
639
|
if @at_start_of_line
|
607
|
-
output
|
640
|
+
output << " " * [@indentation, 0].max
|
608
641
|
end
|
609
642
|
end
|
610
643
|
|
data/lib/erector.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
require "erector/rails"
|
4
|
+
|
5
|
+
# Note: this is *not* inside the rails_root since we're not testing
|
6
|
+
# Erector inside a rails app. We're testing that we can use the command-line
|
7
|
+
# converter tool on a newly generated scaffold app (like we brag about in the
|
8
|
+
# user guide).
|
9
|
+
#
|
10
|
+
module Erector
|
11
|
+
|
12
|
+
describe "the user running this spec" do
|
13
|
+
it "should have the correct Rails gem (version #{Erector::Rails::RAILS_VERSION}) installed" do
|
14
|
+
target_version = Gem::Version.new(Erector::Rails::RAILS_VERSION)
|
15
|
+
dep = Gem::Dependency.new "rails", target_version
|
16
|
+
specs = Gem.source_index.search dep
|
17
|
+
specs.size.should == 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Erect in a Rails app" do
|
22
|
+
|
23
|
+
def run(cmd)
|
24
|
+
puts cmd
|
25
|
+
stdout = `#{cmd}`
|
26
|
+
if $? != 0
|
27
|
+
raise "Command #{cmd} failed, returning '#{stdout}', current dir '#{Dir.getwd}'"
|
28
|
+
else
|
29
|
+
return stdout
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_rails(app_dir)
|
34
|
+
# To ensure we're working with the right version of Rails we use "gem 'rails', 1.2.3"
|
35
|
+
# in a "ruby -e" command line invocation of the rails executable to generate an
|
36
|
+
# app called explode.
|
37
|
+
#
|
38
|
+
puts "Generating fresh rails #{Erector::Rails::RAILS_VERSION} app"
|
39
|
+
run "ruby -e \"require 'rubygems'; gem 'rails', '#{Erector::Rails::RAILS_VERSION}'; load 'rails'\" #{app_dir}"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "works like we say it does in the user guide" do
|
43
|
+
app_dir = Dir.tmpdir + "/#{Time.now.to_i}" + "/explode"
|
44
|
+
erector_bin = File.expand_path("#{File.dirname(__FILE__)}/../../bin")
|
45
|
+
|
46
|
+
FileUtils.mkdir_p(app_dir)
|
47
|
+
run_rails app_dir
|
48
|
+
FileUtils.cd(app_dir, :verbose => true) do
|
49
|
+
run "script/generate scaffold post title:string body:text published:boolean"
|
50
|
+
run "#{erector_bin}/erector app/views/posts"
|
51
|
+
FileUtils.rm_f("app/views/posts/*.erb")
|
52
|
+
run "(echo ''; echo \"require 'erector'\") >> config/environment.rb"
|
53
|
+
run "rake db:migrate"
|
54
|
+
# run "script/server" # todo: launch in background; use mechanize or something to crawl it; then kill it
|
55
|
+
# perhaps use open4?
|
56
|
+
# open http://localhost:3000/posts
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|