erector 0.8.1 → 0.8.2

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.
@@ -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