Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested content_tag throws undefined method `output_buffer=` in simple helper

I'm trying to create a simple view helper but as soon as I try nest a couple of content tags it will throw

NoMethodError: undefined method `output_buffer=' for
def table_for(list, &proc)
  t = Table.new
  proc.call(t)
  t.render_column(list) 
end

class Table
  include ActionView::Helpers::TagHelper

  attr_accessor :columns, :block

  def initialize
    @columns = Array.new
  end

  def col(name)
    @columns << name
  end

  def render_column(list)
    content_tag :table do
      list.each do |c|
        content_tag :td, c
      end
    end
  end
end

Any hints of what's wrong? I've also seen that there's a XmlBuilder is that one better for my purpose?

like image 789
orjan Avatar asked Jan 08 '11 10:01

orjan


2 Answers

ActionView::Base has built into it the Context module, which provides the methods output_buffer() and output_buffer=().

So you can solve your problem either by having your class do:

include ActionView::Context

Or even more simply:

attr_accessor :output_buffer
like image 137
patrick Avatar answered Nov 09 '22 22:11

patrick


I think there were some changes about this in 3.0, but in previous versions the trick was to pass self:

def table_for(list, &proc)
  Table.new(self)
  # ...

def initialize(binding)
  @binding = binding
  #...

def render_column
  @binding.content_tag :table do
    # ...
  end
end

I'm not sure if this is still how it's done in rails 3.

Another thing to fix in ordere for the code to work is to save the output of the inner content_tag somewhere, as with each the content is generated and then discarded. One of the possible solutions:

def render_column(list)
  @binding.content_tag :table do
    list.inject "" do |out, c|
      out << @binding.content_tag(:td, c)
    end.html_safe
  end
end
like image 32
mfilej Avatar answered Nov 10 '22 00:11

mfilej