rails link_to content_tag ruby-on-rails-3

ruby on rails 3 - link_to - Content_tag anidado arroja el método indefinido `output_buffer=` en un simple ayudante



content_tag link_to rails (3)

ActionView :: Base ha incorporado en él el módulo de contexto, que proporciona los métodos output_buffer () y output_buffer = ().

Así que puedes resolver tu problema haciendo que tu clase haga:

include ActionView::Context

O incluso más simplemente:

attr_accessor :output_buffer

Estoy intentando crear un ayudante de visualización simple, pero tan pronto como intente anidar un par de etiquetas de contenido, se lanzará

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

¿Alguna pista de lo que está mal? También he visto que hay un XmlBuilder que es mejor para mi propósito?


Con la ayuda de Nested content_tag lanza el método indefinido `output_buffer =` en un simple ayudante , terminé con la siguiente solución inspirada en la API para 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 %>

Usando el output_buffer directamente y probablemente reinventando la rueda, el código parece

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


Creo que hubo algunos cambios al respecto en 3.0, pero en versiones anteriores, el truco era pasar self :

def table_for(list, &proc) Table.new(self) # ... def initialize(binding) @binding = binding #... def render_column @binding.content_tag :table do # ... end end

No estoy seguro si esto sigue siendo así como se hace en los rieles 3.

Otra cosa que se debe corregir para que el código funcione es guardar la salida del content_tag interno en algún lugar, ya que con each contenido se genera y luego se descarta. Una de las posibles soluciones:

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