christoffer
2011-Apr-14 22:26 UTC
View helper, blocks and capture. Template output is repeated (rails 3)
I''m having some issues with blocks and capture in erb templates, and
the particular problem shows itself in that the expected output in the
template view is repeated due to something related to how capture
works. (Using Rails 3.x)
I have the following view helper:
module ColumnLayoutHelper
def layout_columns(options = {}, &content_block)
raise ArgumentError, "No block given" unless block_given?
layout = ColumnLayoutBuilder.new
layout.configure(options)
content = capture(layout, &content_block)
content_tag(:div, content, layout.main_wrapping, false)
end
end
class ColumnLayoutBuilder < Object
include ActionView::Helpers::TagHelper
include ActionView::Helpers::CaptureHelper
attr_accessor :output_buffer, :column_counter
attr_accessor :main_wrapping
attr_accessor :column_wrapping
def configure(options)
@main_wrapping = options.delete(:main_wrapping)
@column_wrapping = options.delete(:column_wrapping)
end
def column(&block)
raise ArgumentError, "No block given" unless block_given?
@column_counter ||= 0
@column_counter = @column_counter + 1
column_html_options = (column_wrapping ? column_wrapping.dup : {})
|| {}
column_html_options.default = ""
column_html_options[:class] = "column_#{column_counter} " +
column_html_options[:class]
column_content = content_tag(:div, capture(self, &block),
column_html_options,false)
column_content
end
end
--
Now if I use this column builder helper with the following erb
template:
<%= layout_columns do |layout| %>
<%= layout.column do %>
content_01
<% end %>
<%= layout.column do %>
content02
<% end %>
<% end %>
I get the following output.
<div>
content_01
<div class="column_1 ">content_01</div>
content02
<div class="column_2 ">
content_01
<div class="column_1 ">content_01</div>
content02
</div>
</div>
As you can see, the buffer in between the captures doesn''t seem to be
cleared in the separate block scopes. As I sort of expected how
capture would work...
I guess I''m having the same issues as pointed out here
http://stackoverflow.com/questions/4352167/cant-suppress-output-in-nested-block-helper-in-rails-3
Any ideas on how to fix this? Thanks
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung
2011-Apr-14 23:04 UTC
Re: View helper, blocks and capture. Template output is repeated (rails 3)
On 14 Apr 2011, at 23:26, christoffer <christoffer.ahlbin-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m having some issues with blocks and capture in erb templates, and > the particular problem shows itself in that the expected output in the > template view is repeated due to something related to how capture > works. (Using Rails 3.x)Here''s my hunch: capture swaps in a temporary output buffer to capture the output. However because you''ve got your custom builder object, the call to capture inside your builder object is fiddling with the builder''s output buffer attribute, which is neither here nor there because the bits of erb you yield to know nothing of this arrangement an d are writing to the template''s output_buffer If you look at the source for fields_for/Formbuilder you can see that they squirrel away the template object (in your helper method this is just self) for later. You should probably do the same Fred> > > I have the following view helper: > > module ColumnLayoutHelper > > def layout_columns(options = {}, &content_block) > raise ArgumentError, "No block given" unless block_given? > > layout = ColumnLayoutBuilder.new > layout.configure(options) > content = capture(layout, &content_block) > content_tag(:div, content, layout.main_wrapping, false) > > end > > end > > class ColumnLayoutBuilder < Object > > include ActionView::Helpers::TagHelper > include ActionView::Helpers::CaptureHelper > > attr_accessor :output_buffer, :column_counter > attr_accessor :main_wrapping > attr_accessor :column_wrapping > > def configure(options) > @main_wrapping = options.delete(:main_wrapping) > @column_wrapping = options.delete(:column_wrapping) > end > > def column(&block) > > raise ArgumentError, "No block given" unless block_given? > > @column_counter ||= 0 > @column_counter = @column_counter + 1 > > column_html_options = (column_wrapping ? column_wrapping.dup : {}) > || {} > column_html_options.default = "" > column_html_options[:class] = "column_#{column_counter} " + > column_html_options[:class] > column_content = content_tag(:div, capture(self, &block), > column_html_options,false) > column_content > end > > end > > -- > > Now if I use this column builder helper with the following erb > template: > > <%= layout_columns do |layout| %> > <%= layout.column do %> > content_01 > <% end %> > <%= layout.column do %> > content02 > <% end %> > <% end %> > > > I get the following output. > > <div> > content_01 > <div class="column_1 ">content_01</div> > content02 > <div class="column_2 "> > content_01 > <div class="column_1 ">content_01</div> > content02 > </div> > </div> > > > As you can see, the buffer in between the captures doesn''t seem to be > cleared in the separate block scopes. As I sort of expected how > capture would work... > > I guess I''m having the same issues as pointed out here > http://stackoverflow.com/questions/4352167/cant-suppress-output-in-nested-block-helper-in-rails-3 > > Any ideas on how to fix this? Thanks > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.