Ruby on rails 3 嵌套的content_标记在simple helper中抛出未定义的方法`output_buffer=`

Ruby on rails 3 嵌套的content_标记在simple helper中抛出未定义的方法`output_buffer=`,ruby-on-rails-3,Ruby On Rails 3,我正在尝试创建一个简单的视图帮助器,但只要我尝试嵌套两个内容标记,它就会抛出NoMethodError:undefined方法'output_buffer=' NoMethodError: undefined method `output_buffer=' for def table_用于(列表和过程) t=表1.1新 过程调用(t) t、 渲染列(列表) 结束 类表 包括ActionView::Helpers::TagHelper 属性存取器:列,:块 def初始化 @columns=Arra

我正在尝试创建一个简单的视图帮助器,但只要我尝试嵌套两个内容标记,它就会抛出NoMethodError:undefined方法'output_buffer='

NoMethodError: undefined method `output_buffer=' for
def table_用于(列表和过程)
t=表1.1新
过程调用(t)
t、 渲染列(列表)
结束
类表
包括ActionView::Helpers::TagHelper
属性存取器:列,:块
def初始化
@columns=Array.new
结束
def col(姓名)

@专栏我认为在3.0中对此有一些更改,但在以前的版本中,诀窍是通过
self

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

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

def render_column
  @binding.content_tag :table do
    # ...
  end
end
我不确定rails 3是否仍然是这样

为了使代码正常工作,另一件需要修复的事情是将内部content_标记的输出保存在某个地方,就像
每个
一样,内容被生成,然后被丢弃。可能的解决方案之一:

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
def render_列(列表)
@binding.content_标记:表do
list.inject“do | out,c|
在他的帮助下,我最终得到了以下由Formtastic API启发的解决方案

<%= table_for(@users) do |t| %>
   <% t.col :name %>
   <% t.col :email %>
   <% t.col :test, :value => lambda { |u| u.email }, :th => 'Custom column name' %>
   <% t.col :static, :value => 'static value' %>
<% end %>

lambda{| u | u.email},:th=>'自定义列名'>
'静态值'%>
直接使用输出缓冲区,并可能重新设计代码的轮子

module ApplicationHelper
  def table_for(list, &block)
    table = Table.new(self)
    block.call(table)
    table.show(list)
  end

  class Column
    include ActiveSupport::Inflector

    attr_accessor :name, :options

    def initialize(name, options = {})
      @name    = name
      @options = options
    end

    def td_value(item)
      value = options[:td]
      if (value)
        if (value.respond_to?('call'))
          value.call(item)
        else
          value
        end
      else
        item[name]
      end
    end

    def th_value
      options[:th] ||= humanize(name)
    end
  end

  class Table
    include ActionView::Helpers::TagHelper

    attr_accessor :template, :columns

    def initialize(temp)
      @columns  = Array.new
      @template = temp
    end

    def col(name, options = {})
      columns << Column.new(name, options)
    end


    def show(list)
      template.content_tag(:table) do
        template.output_buffer << template.content_tag(:tr) do
          columns.collect do |c|
            template.output_buffer << content_tag(:th, c.th_value)
          end
        end
        list.collect do |item|
          template.output_buffer << template.content_tag(:tr) do
            columns.collect do |c|
              template.output_buffer << template.content_tag(:td, c.td_value(item))
            end
          end
        end
      end
    end

  end
end
模块应用程序助手
def表_用于(列表和块)
表=表。新(自身)
块调用(表)
表.显示(列表)
结束
类列
包含ActiveSupport::拐点
属性访问器:名称,:选项
def初始化(名称,选项={})
@name=name
@选项=选项
结束
def td_值(项目)
值=选项[:td]
如果(值)
if(value.response_to?('call'))
值。调用(项目)
其他的
价值
结束
其他的
项目[名称]
结束
结束
定义th_值
选项[:th]| |=人性化(名称)
结束
结束
类表
包括ActionView::Helpers::TagHelper
属性访问器:模板,:列
def初始化(温度)
@columns=Array.new
@模板=临时
结束
def col(名称,选项={})

columnsActionView::Base内置了上下文模块,它提供了output\u buffer()和output\u buffer=()方法

因此,你可以通过让你的班级做以下事情来解决你的问题:

include ActionView::Context
或者更简单地说:

attr_accessor :output_buffer

将self传递到表中会有所帮助,但我发现很难理解/读取传递到表中的内容。
attr_accessor :output_buffer