Browse files

Fix sinatra integration to handle using a form object inside a partial

  • Loading branch information...
1 parent 8ae8419 commit b970eeae4dd989bf3e13bc815c9ba71441d01aa9 @jeremyevans committed Apr 30, 2012
Showing with 68 additions and 16 deletions.
  1. +39 −15 lib/forme/sinatra.rb
  2. +29 −1 spec/sinatra_integration_spec.rb
View
54 lib/forme/sinatra.rb
@@ -13,7 +13,7 @@ class Form < ::Forme::Form
# Set the template output object when initializing.
def initialize(*)
super
- @output = @opts[:output]
+ @output = @opts[:output] ? @opts[:output] : ''
end
# Serialize the tag and inject it into the output.
@@ -23,35 +23,51 @@ def emit(tag)
# Always return nil, so that use with <%= doesn't cause
# multiple things to be output.
- def inputs(*a)
- super
- nil
+ def inputs(*a, &block)
+ if block
+ capture(block){super}
+ else
+ super
+ end
end
# Always return nil, so that use with <%= doesn't cause
# multiple things to be output.
def form(*a, &block)
- super
- nil
+ if block
+ capture(block){super}
+ else
+ super
+ end
end
# If a block is provided, inject an opening tag into the
# output, inject any given children into the output, yield to the
# block, inject a closing tag into the output, and the return nil
# so that usage with <%= doesn't cause multiple things to be output.
# If a block is not given, just return the tag created.
- def tag(type, attr={}, children=[])
+ def tag(type, attr={}, children=[], &block)
tag = _tag(type, attr, children)
- if block_given?
- emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
- children.each{|c| emit(c)}
- yield self
- emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
+ if block
+ capture(block) do
+ emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
+ children.each{|c| emit(c)}
+ yield self
+ emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
+ end
nil
else
tag
end
end
+
+ def capture(block)
+ buf_was, @output = @output, eval("@_out_buf", block.binding) || @output
+ yield
+ ret = @output
+ @output = buf_was
+ ret
+ end
end
# This is the module used to add the Forme integration
@@ -77,9 +93,17 @@ module ERB
# opening attributes, third if provided is
# +Form+'s options.
def form(obj=nil, attr={}, opts={}, &block)
- h = {:output=>@_out_buf}
- (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
- Form.form(obj, attr, opts, &block)
+ if block
+ h = {:output=>@_out_buf}
+ (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
+ Form.form(obj, attr, opts, &block)
+ else
+ output = ''
+ h = {:output=>output}
+ (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
+ Form.form(obj, attr, opts)
+ output
+ end
end
end
View
30 spec/sinatra_integration_spec.rb
@@ -6,7 +6,7 @@
require(ENV['ERUBIS'] ? 'erubis' : 'erb')
class FormeSinatraTest < Sinatra::Base
- helpers(Forme::Sinatra::Helper)
+ helpers(Forme::Sinatra::ERB)
disable :show_exceptions
enable :raise_errors
@@ -33,6 +33,30 @@ class FormeSinatraTest < Sinatra::Base
END
end
+ get '/nest_sep' do
+ @nest = <<END
+ n1
+ <% f.tag(:div) do %>
+ n2
+ <%= f.input(:first) %>
+ <%= f.input(:last) %>
+ n3
+ <% end %>
+ n4
+END
+ erb <<END
+0
+<% form([:foo, :bar], :action=>'/baz') do |f| %>
+ 1
+ <%= f.tag(:p, {}, 'FBB') %>
+ 2
+ <%= erb(@nest, :locals=>{:f=>f}) %>
+ 3
+<% end %>
+4
+END
+ end
+
get '/hash' do
erb "<% form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <% end %>"
end
@@ -78,6 +102,10 @@ def o.puts(*) end
sin_get('/nest').should == '<form action="/baz"> <p>FBB</p> <div> <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> </div> </form>'
end
+ specify "#form should correctly handle situation where multiple templates are used with same form object" do
+ sin_get('/nest_sep').should == "0 <form action=\"/baz\"> 1 <p>FBB</p> 2 n1 <div> n2 <input id=\"first\" name=\"first\" type=\"text\" value=\"foo\"/> <input id=\"last\" name=\"last\" type=\"text\" value=\"bar\"/> n3 </div> n4 3 </form>4"
+ end
+
specify "#form should accept two hashes instead of requiring obj as first argument" do
sin_get('/hash').should == '<form action="/baz"> <input id="first" name="first" type="text" value="foo"/> </form>'
end

0 comments on commit b970eea

Please sign in to comment.