erector 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 8
4
- :patch: 1
4
+ :patch: 2
@@ -24,6 +24,7 @@ require "erector/html"
24
24
  require "erector/convenience"
25
25
  require "erector/jquery"
26
26
  require "erector/sass"
27
+ require "erector/abstract_widget"
27
28
  require "erector/widget"
28
29
 
29
30
  require "erector/inline"
@@ -0,0 +1,172 @@
1
+ module Erector
2
+
3
+ # Abstract base class for Widget. This pattern allows Widget to include lots of nicely organized modules and still
4
+ # have proper semantics for "super" in subclasses. See the rdoc for Widget for the list of all the included modules.
5
+ class AbstractWidget
6
+ @@prettyprint_default = false
7
+ def prettyprint_default
8
+ @@prettyprint_default
9
+ end
10
+
11
+ def self.prettyprint_default
12
+ @@prettyprint_default
13
+ end
14
+
15
+ def self.prettyprint_default=(enabled)
16
+ @@prettyprint_default = enabled
17
+ end
18
+
19
+ def self.inline(*args, &block)
20
+ Class.new(self) do
21
+ include Erector::Inline
22
+ end.new(*args, &block)
23
+ end
24
+
25
+ [:helpers, :assigns, :output, :parent, :block].each do |attr|
26
+ class_eval(<<-SRC, __FILE__, __LINE__ + 1)
27
+ def #{attr}
28
+ @_#{attr}
29
+ end
30
+ SRC
31
+ end
32
+
33
+ def initialize(assigns = {}, &block)
34
+ unless assigns.is_a? Hash
35
+ raise "Erector widgets are initialized with only a parameter hash. (Other parameters are passed to to_html, or the #widget method.)"
36
+ end
37
+
38
+ @_assigns = assigns
39
+
40
+ assigns.each do |name, value|
41
+ instance_variable_set(name.to_s[0..0] == '@' ? name : "@#{name}", value)
42
+ end
43
+
44
+ @_parent = eval("self", block.binding) if block
45
+ @_block = block
46
+ end
47
+
48
+ # Entry point for rendering a widget (and all its children). This method
49
+ # creates a new output string (if necessary), calls this widget's #content
50
+ # method and returns the string.
51
+ #
52
+ # Options:
53
+ # output:: the string to output to. Default: a new empty string
54
+ # prettyprint:: whether Erector should add newlines and indentation.
55
+ # Default: the value of prettyprint_default (which is false
56
+ # by default).
57
+ # indentation:: the amount of spaces to indent. Ignored unless prettyprint
58
+ # is true.
59
+ # max_length:: preferred maximum length of a line. Line wraps will only
60
+ # occur at space characters, so a long word may end up creating
61
+ # a line longer than this. If nil (default), then there is no
62
+ # arbitrary limit to line lengths, and only internal newline
63
+ # characters and prettyprinting will determine newlines in the
64
+ # output.
65
+ # helpers:: a helpers object containing utility methods. Usually this is a
66
+ # Rails view object.
67
+ # content_method_name:: in case you want to call a method other than
68
+ # #content, pass its name in here.
69
+ def to_html(options = {})
70
+ raise "Erector::Widget#to_html takes an options hash, not a symbol. Try calling \"to_html(:content_method_name=> :#{options})\"" if options.is_a? Symbol
71
+ _render(options).to_s
72
+ end
73
+
74
+ # alias for #to_html
75
+ # @deprecated Please use {#to_html} instead
76
+ def to_s(*args)
77
+ unless defined? @@already_warned_to_s
78
+ $stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
79
+ @@already_warned_to_s = true
80
+ end
81
+ to_html(*args)
82
+ end
83
+
84
+ # Entry point for rendering a widget (and all its children). Same as #to_html
85
+ # only it returns an array, for theoretical performance improvements when using a
86
+ # Rack server (like Sinatra or Rails Metal).
87
+ #
88
+ # # Options: see #to_html
89
+ def to_a(options = {})
90
+ _render(options).to_a
91
+ end
92
+
93
+ # Template method which must be overridden by all widget subclasses.
94
+ # Inside this method you call the magic #element methods which emit HTML
95
+ # and text to the output string. If you call "super" (or don't override
96
+ # +content+, or explicitly call "call_block") then your widget will
97
+ # execute the block that was passed into its constructor. The semantics of
98
+ # this block are confusing; make sure to read the rdoc for Erector#call_block
99
+ def content
100
+ call_block
101
+ end
102
+
103
+ # When this method is executed, the default block that was passed in to
104
+ # the widget's constructor will be executed. The semantics of this
105
+ # block -- that is, what "self" is, and whether it has access to
106
+ # Erector methods like "div" and "text", and the widget's instance
107
+ # variables -- can be quite confusing. The rule is, most of the time the
108
+ # block is evaluated using "call" or "yield", which means that its scope
109
+ # is that of the caller. So if that caller is not an Erector widget, it
110
+ # will *not* have access to the Erector methods, but it *will* have access
111
+ # to instance variables and methods of the calling object.
112
+ #
113
+ # If you want this block to have access to Erector methods then use
114
+ # Erector::Inline#content or Erector#inline.
115
+ def call_block
116
+ @_block.call(self) if @_block
117
+ end
118
+
119
+ # Emits a (nested) widget onto the current widget's output stream. Accepts
120
+ # either a class or an instance. If the first argument is a class, then
121
+ # the second argument is a hash used to populate its instance variables.
122
+ # If the first argument is an instance then the hash must be unspecified
123
+ # (or empty). If a block is passed to this method, then it gets set as the
124
+ # rendered widget's block.
125
+ #
126
+ # This is the preferred way to call one widget from inside another. This
127
+ # method assures that the same output string is used, which gives better
128
+ # performance than using +capture+ or +to_html+.
129
+ def widget(target, assigns = {}, options = {}, &block)
130
+ if target.is_a? Class
131
+ target.new(assigns, &block)._render_via(self, options)
132
+ else
133
+ unless assigns.empty?
134
+ raise "Unexpected second parameter. Did you mean to pass in assigns when you instantiated the #{target.class.to_s}?"
135
+ end
136
+ target._render_via(self, options, &block)
137
+ end
138
+ end
139
+
140
+ # Creates a whole new output string, executes the block, then converts the
141
+ # output string to a string and returns it as raw text. If at all possible
142
+ # you should avoid this method since it hurts performance, and use +widget+
143
+ # instead.
144
+ def capture
145
+ original, @_output = output, Output.new
146
+ yield
147
+ original.widgets.concat(output.widgets) # todo: test!!!
148
+ output.to_s
149
+ ensure
150
+ @_output = original
151
+ end
152
+
153
+ protected
154
+ def _render(options = {}, &block)
155
+ @_block = block if block
156
+ @_parent = options[:parent] || parent
157
+ @_helpers = options[:helpers] || parent
158
+ @_output = options[:output]
159
+ @_output = Output.new(options) unless output.is_a?(Output)
160
+
161
+ output.widgets << self.class
162
+ send(options[:content_method_name] || :content)
163
+ output
164
+ end
165
+
166
+ def _render_via(parent, options = {}, &block)
167
+ _render(options.merge(:parent => parent,
168
+ :output => parent.output,
169
+ :helpers => parent.helpers), &block)
170
+ end
171
+ end
172
+ end
@@ -17,5 +17,14 @@ module Erector
17
17
  self.text == other.text and
18
18
  self.options == other.options) ? true : false
19
19
  end
20
+
21
+ def eql?(other)
22
+ self == other
23
+ end
24
+
25
+ def hash
26
+ # this is a fairly inefficient hash function but it does the trick for now
27
+ "#{type}#{text}#{options}".hash
28
+ end
20
29
  end
21
30
  end
@@ -1,8 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'treetop'
3
- dir = File.dirname(__FILE__)
4
- require "#{dir}/indenting"
5
- Treetop.load("#{dir}/rhtml.treetop")
3
+
4
+ require "#{File.dirname(__FILE__)}/indenting"
5
+ Treetop.load("#{File.dirname(__FILE__)}/rhtml.treetop")
6
6
 
7
7
  module Erector
8
8
  class Erected
@@ -72,4 +72,4 @@ module Erector
72
72
  filename.split("_").map{|part| part.capitalize}.join
73
73
  end
74
74
  end
75
- end
75
+ end
@@ -1,13 +1,13 @@
1
1
  module Erector
2
2
  module HTML
3
3
  module ClassMethods
4
- # Tags which are always self-closing. Click "[Source]" to see the full list.
4
+ # Tags which are always self-closing. Click "[show source]" to see the full list.
5
5
  def empty_tags
6
6
  ['area', 'base', 'br', 'col', 'embed', 'frame',
7
7
  'hr', 'img', 'input', 'link', 'meta', 'param']
8
8
  end
9
9
 
10
- # Tags which can contain other stuff. Click "[Source]" to see the full list.
10
+ # Tags which can contain other stuff. Click "[show source]" to see the full list.
11
11
  def full_tags
12
12
  [
13
13
  'a', 'abbr', 'acronym', 'address', 'article', 'aside', 'audio',
@@ -281,17 +281,20 @@ module Erector
281
281
  end
282
282
  attributes ||= {}
283
283
  open_tag tag_name, attributes
284
- if block && value
285
- raise ArgumentError, "You can't pass both a block and a value to #{tag_name} -- please choose one."
286
- end
287
- if block
288
- block.call
289
- elsif raw
290
- text! value
291
- else
292
- text value
284
+ begin
285
+ if block && value
286
+ raise ArgumentError, "You can't pass both a block and a value to #{tag_name} -- please choose one."
287
+ end
288
+ if block
289
+ block.call
290
+ elsif raw
291
+ text! value
292
+ else
293
+ text value
294
+ end
295
+ ensure
296
+ close_tag tag_name
293
297
  end
294
- close_tag tag_name
295
298
  end
296
299
 
297
300
  def __empty_element__(tag_name, attributes={})
@@ -82,12 +82,12 @@ module Erector
82
82
 
83
83
  missing = self.class.needed_variables - assigned
84
84
  unless missing.empty? || missing == [nil]
85
- raise "Missing parameter#{missing.size == 1 ? '' : 's'}: #{missing.join(', ')}"
85
+ raise "Missing parameter#{missing.size == 1 ? '' : 's'} for #{self.class.name}: #{missing.join(', ')}"
86
86
  end
87
87
 
88
88
  excess = assigned - self.class.needed_variables
89
89
  unless self.class.needed_variables.empty? || excess.empty?
90
- raise("Excess parameter#{excess.size == 1 ? '' : 's'}: #{excess.join(', ')}")
90
+ raise("Excess parameter#{excess.size == 1 ? '' : 's'} for #{self.class.name}: #{excess.join(', ')}")
91
91
  end
92
92
  end
93
93
  end
@@ -1,11 +1,11 @@
1
1
  module Erector
2
2
 
3
- # A Widget is the center of the Erector universe.
3
+ # A Widget is the center of the Erector universe.
4
4
  #
5
5
  # To create a widget, extend Erector::Widget and implement the +content+
6
6
  # method. Inside this method you may call any of the tag methods like +span+
7
- # or +p+ to emit HTML/XML tags.
8
- #
7
+ # or +p+ to emit HTML/XML tags.
8
+ #
9
9
  # You can also define a widget on the fly by passing a block to +new+. This
10
10
  # block will get executed when the widget's +content+ method is called. See
11
11
  # the userguide for important details about the scope of this block when run --
@@ -17,193 +17,30 @@ module Erector
17
17
  # A widget's +new+ method optionally accepts an options hash. Entries in
18
18
  # this hash are converted to instance variables.
19
19
  #
20
- # You can add runtime input checking via the +needs+ macro. See #needs.
20
+ # You can add runtime input checking via the +needs+ macro. See #needs.
21
21
  # This mechanism is meant to ameliorate development-time confusion about
22
22
  # exactly what parameters are supported by a given widget, avoiding
23
23
  # confusing runtime NilClass errors.
24
- #
24
+ #
25
25
  # To call one widget from another, inside the parent widget's +content+
26
26
  # method, instantiate the child widget and call the +widget+ method. This
27
27
  # assures that the same output stream is used, which gives better
28
28
  # performance than using +capture+ or +to_html+. It also preserves the
29
29
  # indentation and helpers of the enclosing class.
30
- #
30
+ #
31
31
  # In this documentation we've tried to keep the distinction clear between
32
32
  # methods that *emit* text and those that *return* text. "Emit" means that
33
33
  # it writes to the output stream; "return" means that it returns a string
34
34
  # like a normal method and leaves it up to the caller to emit that string if
35
35
  # it wants.
36
36
  #
37
+ # This class extends AbstractWidget and includes several modules,
38
+ # so be sure to check all of those places for API documentation for the
39
+ # various methods of Widget. Also read the API Cheatsheet in the user guide
40
+ # at http://erector.rubyforge.org/userguide#apicheatsheet
41
+ #
37
42
  # Now, seriously, after playing around a bit, go read the user guide. It's
38
- # fun!
39
- class AbstractWidget
40
- @@prettyprint_default = false
41
- def prettyprint_default
42
- @@prettyprint_default
43
- end
44
-
45
- def self.prettyprint_default
46
- @@prettyprint_default
47
- end
48
-
49
- def self.prettyprint_default=(enabled)
50
- @@prettyprint_default = enabled
51
- end
52
-
53
- def self.inline(*args, &block)
54
- Class.new(self) do
55
- include Erector::Inline
56
- end.new(*args, &block)
57
- end
58
-
59
- [:helpers, :assigns, :output, :parent, :block].each do |attr|
60
- class_eval(<<-SRC, __FILE__, __LINE__ + 1)
61
- def #{attr}
62
- @_#{attr}
63
- end
64
- SRC
65
- end
66
-
67
- def initialize(assigns = {}, &block)
68
- unless assigns.is_a? Hash
69
- raise "Erector widgets are initialized with only a parameter hash. (Other parameters are passed to to_html, or the #widget method.)"
70
- end
71
-
72
- @_assigns = assigns
73
-
74
- assigns.each do |name, value|
75
- instance_variable_set(name.to_s[0..0] == '@' ? name : "@#{name}", value)
76
- end
77
-
78
- @_parent = eval("self", block.binding) if block
79
- @_block = block
80
- end
81
-
82
- # Entry point for rendering a widget (and all its children). This method
83
- # creates a new output string (if necessary), calls this widget's #content
84
- # method and returns the string.
85
- #
86
- # Options:
87
- # output:: the string to output to. Default: a new empty string
88
- # prettyprint:: whether Erector should add newlines and indentation.
89
- # Default: the value of prettyprint_default (which is false
90
- # by default).
91
- # indentation:: the amount of spaces to indent. Ignored unless prettyprint
92
- # is true.
93
- # max_length:: preferred maximum length of a line. Line wraps will only
94
- # occur at space characters, so a long word may end up creating
95
- # a line longer than this. If nil (default), then there is no
96
- # arbitrary limit to line lengths, and only internal newline
97
- # characters and prettyprinting will determine newlines in the
98
- # output.
99
- # helpers:: a helpers object containing utility methods. Usually this is a
100
- # Rails view object.
101
- # content_method_name:: in case you want to call a method other than
102
- # #content, pass its name in here.
103
- def to_html(options = {})
104
- raise "Erector::Widget#to_html takes an options hash, not a symbol. Try calling \"to_html(:content_method_name=> :#{options})\"" if options.is_a? Symbol
105
- _render(options).to_s
106
- end
107
-
108
- # alias for #to_html
109
- # @deprecated Please use {#to_html} instead
110
- def to_s(*args)
111
- unless defined? @@already_warned_to_s
112
- $stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
113
- @@already_warned_to_s = true
114
- end
115
- to_html(*args)
116
- end
117
-
118
- # Entry point for rendering a widget (and all its children). Same as #to_html
119
- # only it returns an array, for theoretical performance improvements when using a
120
- # Rack server (like Sinatra or Rails Metal).
121
- #
122
- # # Options: see #to_html
123
- def to_a(options = {})
124
- _render(options).to_a
125
- end
126
-
127
- # Template method which must be overridden by all widget subclasses.
128
- # Inside this method you call the magic #element methods which emit HTML
129
- # and text to the output string. If you call "super" (or don't override
130
- # +content+, or explicitly call "call_block") then your widget will
131
- # execute the block that was passed into its constructor. The semantics of
132
- # this block are confusing; make sure to read the rdoc for Erector#call_block
133
- def content
134
- call_block
135
- end
136
-
137
- # When this method is executed, the default block that was passed in to
138
- # the widget's constructor will be executed. The semantics of this
139
- # block -- that is, what "self" is, and whether it has access to
140
- # Erector methods like "div" and "text", and the widget's instance
141
- # variables -- can be quite confusing. The rule is, most of the time the
142
- # block is evaluated using "call" or "yield", which means that its scope
143
- # is that of the caller. So if that caller is not an Erector widget, it
144
- # will *not* have access to the Erector methods, but it *will* have access
145
- # to instance variables and methods of the calling object.
146
- #
147
- # If you want this block to have access to Erector methods then use
148
- # Erector::Inline#content or Erector#inline.
149
- def call_block
150
- @_block.call(self) if @_block
151
- end
152
-
153
- # Emits a (nested) widget onto the current widget's output stream. Accepts
154
- # either a class or an instance. If the first argument is a class, then
155
- # the second argument is a hash used to populate its instance variables.
156
- # If the first argument is an instance then the hash must be unspecified
157
- # (or empty). If a block is passed to this method, then it gets set as the
158
- # rendered widget's block.
159
- #
160
- # This is the preferred way to call one widget from inside another. This
161
- # method assures that the same output string is used, which gives better
162
- # performance than using +capture+ or +to_html+.
163
- def widget(target, assigns = {}, options = {}, &block)
164
- if target.is_a? Class
165
- target.new(assigns, &block)._render_via(self, options)
166
- else
167
- unless assigns.empty?
168
- raise "Unexpected second parameter. Did you mean to pass in assigns when you instantiated the #{target.class.to_s}?"
169
- end
170
- target._render_via(self, options, &block)
171
- end
172
- end
173
-
174
- # Creates a whole new output string, executes the block, then converts the
175
- # output string to a string and returns it as raw text. If at all possible
176
- # you should avoid this method since it hurts performance, and use +widget+
177
- # instead.
178
- def capture
179
- original, @_output = output, Output.new
180
- yield
181
- original.widgets.concat(output.widgets) # todo: test!!!
182
- output.to_s
183
- ensure
184
- @_output = original
185
- end
186
-
187
- protected
188
- def _render(options = {}, &block)
189
- @_block = block if block
190
- @_parent = options[:parent] || parent
191
- @_helpers = options[:helpers] || parent
192
- @_output = options[:output]
193
- @_output = Output.new(options) unless output.is_a?(Output)
194
-
195
- output.widgets << self.class
196
- send(options[:content_method_name] || :content)
197
- output
198
- end
199
-
200
- def _render_via(parent, options = {}, &block)
201
- _render(options.merge(:parent => parent,
202
- :output => parent.output,
203
- :helpers => parent.helpers), &block)
204
- end
205
- end
206
-
43
+ # fun!
207
44
  class Widget < AbstractWidget
208
45
  include Erector::HTML
209
46
  include Erector::Needs
@@ -13,6 +13,7 @@ describe Erector::Convenience do
13
13
  end
14
14
 
15
15
  it "passes extra options through to to_html" do
16
+ pending "RR problem with Ruby 1.9" if RUBY_VERSION >= "1.9.0"
16
17
  widget = Erector.inline do
17
18
  div "foo"
18
19
  end
@@ -28,19 +28,40 @@ module DependencySpec
28
28
  x.text.should == "sample file contents, 2 + 2 = 4\n"
29
29
  end
30
30
 
31
- it "is equal to an identical external" do
32
- x = Erector::Dependency.new(:foo, "abc", {:bar => 7})
33
- y = Erector::Dependency.new(:foo, "abc", {:bar => 7})
34
- x.should == y
35
- [x].should include(y)
36
- end
31
+ describe "comparison methods" do
32
+ before do
33
+ @castor = Erector::Dependency.new(:foo, "abc", {:bar => 7})
34
+ @pollux = Erector::Dependency.new(:foo, "abc", {:bar => 7})
35
+ @leo = Erector::Dependency.new(:foo, "abc")
36
+ @pisces = Erector::Dependency.new(:foo, "xyz", {:bar => 7})
37
+ end
37
38
 
38
- it "is not equal to an otherwise identical external with different options" do
39
- x = Erector::Dependency.new(:foo, "abc")
40
- y = Erector::Dependency.new(:foo, "abc", {:bar => 7})
41
- x.should_not == y
42
- [x].should_not include(y)
43
- end
39
+ it "is equal to an identical external" do
40
+ @castor.should == @pollux
41
+ [@castor].should include(@pollux)
42
+ @castor.eql?(@pollux).should be_true
43
+ @castor.hash.should == @pollux.hash
44
+ end
44
45
 
46
+ it "is not equal to an otherwise identical external with different options" do
47
+ @castor.should_not == @leo
48
+ [@castor].should_not include(@leo)
49
+ @castor.eql?(@leo).should_not be_true
50
+ @castor.hash.should_not == @leo.hash
51
+ end
52
+
53
+ it "is not equal to a different external with the same options" do
54
+ @castor.should_not == @pisces
55
+ [@castor].should_not include(@pisces)
56
+ @castor.eql?(@pisces).should_not be_true
57
+ @castor.hash.should_not == @pisces.hash
58
+ end
59
+
60
+ # see http://blog.nathanielbibler.com/post/73525836/using-the-ruby-array-uniq-with-custom-classes
61
+ it "works with uniq" do
62
+ [@castor, @pollux, @leo].uniq.should == [@castor, @leo]
63
+ end
64
+
65
+ end
45
66
  end
46
67
  end
@@ -16,6 +16,7 @@ module ExternalsSpec
16
16
  end
17
17
 
18
18
  it "calls #interpret_args with given arguments and passes result to #push_dependency" do
19
+ pending "RR problem with Ruby 1.9" if RUBY_VERSION >= "1.9.0"
19
20
  mock(Erector::Widget).interpret_args(*@args).returns(@result)
20
21
  Erector::Widget.depends_on *@args
21
22
  end
@@ -0,0 +1,18 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+ $: << "#{here}/../../lib"
3
+
4
+ require "erector"
5
+
6
+ class Hello < Erector::Widget
7
+ def content
8
+ html do
9
+ head do
10
+ title "Welcome page"
11
+ end
12
+ body do
13
+ p "Hello, world"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ puts Hello.new.to_html
@@ -0,0 +1,12 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+ require File.expand_path("#{here}/../spec_helper")
3
+
4
+ describe "Hello World example from README" do
5
+ it "works" do
6
+ Dir.chdir(here) do
7
+ clear_bundler_env
8
+ html = sys "ruby hello_from_readme.rb"
9
+ html.should == "<html><head><title>Welcome page</title></head><body><p>Hello, world</p></body></html>\n"
10
+ end
11
+ end
12
+ end
@@ -506,4 +506,45 @@ describe Erector::HTML do
506
506
  erector { close_tag :foo; close_tag :bar }.should == "</foo></bar>"
507
507
  end
508
508
  end
509
+
510
+ describe "exception handling" do
511
+ class RenderWithReturn < Erector::Widget
512
+ def content
513
+ h2 do
514
+ return "returned_value"
515
+ text "don't get here"
516
+ end
517
+ end
518
+ end
519
+
520
+ it "closes tags when a block returns" do
521
+ RenderWithReturn.new.to_html.should == "<h2></h2>"
522
+ end
523
+
524
+ it "closes tags when a block throws and the exception is caught" do
525
+ erector do
526
+ begin
527
+ div do
528
+ raise "no way"
529
+ text "not reached"
530
+ end
531
+ rescue
532
+ end
533
+ end.should == "<div></div>"
534
+ end
535
+
536
+ it "closes tags when throwing block versus text exception" do
537
+ erector do
538
+ begin
539
+ span "a value" do
540
+ text "a block"
541
+ end
542
+ rescue ArgumentError => e
543
+ e.to_s.should include(
544
+ "You can't pass both a block and a value")
545
+ end
546
+ end.should == "<span></span>"
547
+ end
548
+ end
549
+
509
550
  end
@@ -193,7 +193,7 @@ module Erector
193
193
  @output.widgets << Puppy
194
194
  @output.widgets << Kitten
195
195
  @output.widgets << Puppy
196
- @output.widgets.to_a.should include_only [Puppy, Kitten]
196
+ @output.widgets.to_a.should include_only([Puppy, Kitten])
197
197
  end
198
198
  end
199
199
  end
@@ -7,17 +7,17 @@ RAILS_LOAD_PATHS.each do |path|
7
7
  end
8
8
 
9
9
  require "rubygems"
10
+ require "bundler"
11
+ Bundler.setup
12
+
10
13
  require "erector"
11
14
  require "nokogiri"
12
15
  require "rr"
13
16
  require 'tempfile'
14
17
  require 'ostruct'
15
- require "spec"
16
- require "spec/autorun"
17
-
18
- Spec::Runner.configure do |config|
19
- config.mock_with :rr
20
- end
18
+ require "rspec"
19
+ require "rspec/autorun"
20
+ require "open3"
21
21
 
22
22
  unless '1.9'.respond_to?(:force_encoding)
23
23
  String.class_eval do
@@ -68,8 +68,9 @@ module Matchers
68
68
  end
69
69
  end
70
70
 
71
- Spec::Runner.configure do |config|
71
+ RSpec.configure do |config|
72
72
  include Matchers
73
+ config.mock_with :rr
73
74
  end
74
75
 
75
76
  def capturing_output
@@ -90,3 +91,30 @@ ensure
90
91
  $stderr = STDERR
91
92
  end
92
93
 
94
+ def sys(cmd, expected_status = 0)
95
+ start_time = Time.now
96
+ $stderr.print cmd
97
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thread|
98
+ # in Ruby 1.8, wait_thread is nil :-( so just pretend the process was successful (status 0)
99
+ exit_status = (wait_thread.value.exitstatus if wait_thread) || 0
100
+ output = stdout.read # + stderr.read #todo: make stderr optional
101
+ unless expected_status.nil?
102
+ unless exit_status == expected_status
103
+ $stderr.puts " => #{exit_status}"
104
+ puts output
105
+ exit_status.should == expected_status
106
+ end
107
+ # assert { output and exit_status == expected_status }
108
+ end
109
+ yield output if block_given?
110
+ output
111
+ end
112
+ ensure
113
+ $stderr.puts " (#{"%.2f" % (Time.now - start_time)} sec)"
114
+ end
115
+
116
+ def clear_bundler_env
117
+ # Bundler inherits its environment by default, so clear it here
118
+ %w{BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE}.each { |var| ENV.delete(var) }
119
+ end
120
+
metadata CHANGED
@@ -1,49 +1,58 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: erector
3
- version: !ruby/object:Gem::Version
4
- hash: 61
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 8
9
- - 1
10
- version: 0.8.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.2
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
13
- - Pivotal Labs
7
+ authors:
8
+ - Alex Chaffee
9
+ - Brian Takita
10
+ - Jeff Dean
11
+ - Jim Kingdon
14
12
  autorequire:
15
13
  bindir: bin
16
14
  cert_chain: []
17
-
18
- date: 2010-07-17 00:00:00 -07:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: hoe
15
+ date: 2011-02-16 00:00:00.000000000 -08:00
16
+ default_executable: erector
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
19
+ name: treetop
20
+ requirement: &2158316440 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ! '>='
24
+ - !ruby/object:Gem::Version
25
+ version: 1.2.3
26
+ type: :runtime
23
27
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
28
+ version_requirements: *2158316440
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: &2158315880 !ruby/object:Gem::Requirement
25
32
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 1
32
- - 5
33
- - 0
34
- version: 1.5.0
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
35
37
  type: :runtime
36
- version_requirements: *id001
37
- description: Html Builder library.
38
- email: erector@googlegroups.compivotallabsopensource@googlegroups.com
39
- executables:
38
+ prerelease: false
39
+ version_requirements: *2158315880
40
+ description: Erector is a Builder-like view framework, inspired by Markaby but overcoming
41
+ some of its flaws. In Erector all views are objects, not template files, which allows
42
+ the full power of object-oriented programming (inheritance, modular decomposition,
43
+ encapsulation) in views.
44
+ email: erector@googlegroups.com
45
+ executables:
40
46
  - erector
41
47
  extensions: []
42
-
43
- extra_rdoc_files:
48
+ extra_rdoc_files:
44
49
  - README.txt
45
- - spec/erector/sample-file.txt
46
- files:
50
+ files:
51
+ - README.txt
52
+ - VERSION.yml
53
+ - bin/erector
54
+ - lib/erector.rb
55
+ - lib/erector/abstract_widget.rb
47
56
  - lib/erector/after_initialize.rb
48
57
  - lib/erector/caching.rb
49
58
  - lib/erector/convenience.rb
@@ -63,6 +72,7 @@ files:
63
72
  - lib/erector/mixin.rb
64
73
  - lib/erector/needs.rb
65
74
  - lib/erector/output.rb
75
+ - lib/erector/rails.rb
66
76
  - lib/erector/rails/extensions/action_controller.rb
67
77
  - lib/erector/rails/extensions/rails_helpers.rb
68
78
  - lib/erector/rails/extensions/rails_widget.rb
@@ -70,25 +80,20 @@ files:
70
80
  - lib/erector/rails/rails_version.rb
71
81
  - lib/erector/rails/template_handlers/ert_handler.rb
72
82
  - lib/erector/rails/template_handlers/rb_handler.rb
73
- - lib/erector/rails.rb
74
83
  - lib/erector/raw_string.rb
75
84
  - lib/erector/sass.rb
76
85
  - lib/erector/unicode.rb
77
86
  - lib/erector/unicode_builder.rb
78
87
  - lib/erector/version.rb
79
88
  - lib/erector/widget.rb
89
+ - lib/erector/widgets.rb
80
90
  - lib/erector/widgets/environment_badge.rb
81
91
  - lib/erector/widgets/external_renderer.rb
82
92
  - lib/erector/widgets/field_table.rb
83
93
  - lib/erector/widgets/form.rb
84
94
  - lib/erector/widgets/page.rb
85
95
  - lib/erector/widgets/table.rb
86
- - lib/erector/widgets.rb
87
- - lib/erector.rb
88
96
  - rails/init.rb
89
- - README.txt
90
- - VERSION.yml
91
- - bin/erector
92
97
  - spec/erect/erect_rails_spec.rb
93
98
  - spec/erect/erect_spec.rb
94
99
  - spec/erect/erected_spec.rb
@@ -97,6 +102,8 @@ files:
97
102
  - spec/erector/convenience_spec.rb
98
103
  - spec/erector/dependency_spec.rb
99
104
  - spec/erector/externals_spec.rb
105
+ - spec/erector/hello_from_readme.rb
106
+ - spec/erector/hello_from_readme_spec.rb
100
107
  - spec/erector/html_spec.rb
101
108
  - spec/erector/indentation_spec.rb
102
109
  - spec/erector/inline_spec.rb
@@ -114,39 +121,58 @@ files:
114
121
  - spec/erector/widgets/table_spec.rb
115
122
  - spec/spec_helper.rb
116
123
  has_rdoc: true
117
- homepage: http://erector.rubyforge.org
124
+ homepage: http://erector.rubyforge.org/
118
125
  licenses: []
119
-
120
126
  post_install_message:
121
- rdoc_options:
122
- - --main
123
- - README.txt
124
- require_paths:
127
+ rdoc_options:
128
+ - --charset=UTF-8
129
+ require_paths:
125
130
  - lib
126
- required_ruby_version: !ruby/object:Gem::Requirement
131
+ required_ruby_version: !ruby/object:Gem::Requirement
127
132
  none: false
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- hash: 3
132
- segments:
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ segments:
133
138
  - 0
134
- version: "0"
135
- required_rubygems_version: !ruby/object:Gem::Requirement
139
+ hash: 3942824524895088224
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
141
  none: false
137
- requirements:
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- hash: 3
141
- segments:
142
- - 0
143
- version: "0"
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
144
146
  requirements: []
145
-
146
147
  rubyforge_project: erector
147
- rubygems_version: 1.3.7
148
+ rubygems_version: 1.5.2
148
149
  signing_key:
149
150
  specification_version: 3
150
151
  summary: Html Builder library.
151
- test_files: []
152
-
152
+ test_files:
153
+ - spec/erect/erect_rails_spec.rb
154
+ - spec/erect/erect_spec.rb
155
+ - spec/erect/erected_spec.rb
156
+ - spec/erect/rhtml_parser_spec.rb
157
+ - spec/erector/caching_spec.rb
158
+ - spec/erector/convenience_spec.rb
159
+ - spec/erector/dependency_spec.rb
160
+ - spec/erector/externals_spec.rb
161
+ - spec/erector/hello_from_readme.rb
162
+ - spec/erector/hello_from_readme_spec.rb
163
+ - spec/erector/html_spec.rb
164
+ - spec/erector/indentation_spec.rb
165
+ - spec/erector/inline_spec.rb
166
+ - spec/erector/jquery_spec.rb
167
+ - spec/erector/mixin_spec.rb
168
+ - spec/erector/needs_spec.rb
169
+ - spec/erector/output_spec.rb
170
+ - spec/erector/sample-file.txt
171
+ - spec/erector/sass_spec.rb
172
+ - spec/erector/unicode_builder_spec.rb
173
+ - spec/erector/widget_spec.rb
174
+ - spec/erector/widgets/field_table_spec.rb
175
+ - spec/erector/widgets/form_spec.rb
176
+ - spec/erector/widgets/page_spec.rb
177
+ - spec/erector/widgets/table_spec.rb
178
+ - spec/spec_helper.rb