Вложенный тег content_tag создает простой метод `output_buffer =` в простом помощнике - PullRequest
27 голосов
/ 08 января 2011

Я пытаюсь создать простой помощник вида, но как только я попытаюсь вложить пару тегов контента, он выдаст

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

Любые намеки на то, что не так? Я также видел, что есть XmlBuilder, что лучше для моих целей?

Ответы [ 3 ]

70 голосов
/ 27 сентября 2011

ActionView :: Base имеет встроенный модуль Context, который предоставляет методы output_buffer () и output_buffer = ().

Таким образом, вы можете решить свою проблему, сделав урок:

include ActionView::Context

Или еще проще:

attr_accessor :output_buffer
2 голосов
/ 08 января 2011

Я думаю, что в 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

Я не уверен, что все еще так, как это делается в рельсах 3.

Еще одна вещь, которую нужно исправить в ordere, чтобы код работал, - это сохранить выходные данные внутреннего тега content_tag где-нибудь, как в случае each, контент генерируется, а затем отбрасывается. Одно из возможных решений:

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
0 голосов
/ 11 января 2011

С помощью Вложенный content_tag выбрасывает неопределенный метод `output_buffer =` в простой помощник В результате я получил следующее решение, основанное на API для Formtastic.

<%= 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 %>

При непосредственном использовании output_buffer и, возможно, изобретении колеса, код выглядит как

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...