2011-01-08 5 views
22

Próbuję utworzyć prosty widok pomocnika, ale jak tylko próbuję gniazdo para znaczników treści będzie rzucać Zagnieżdżony content_tag rzuca metodę niezdefiniowany `output_buffer =` prostym pomocnika

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 

żadnych wskazówek co jest nie tak? Widziałem również, że istnieje XmlBuilder jest to lepiej dla mojego celu?

Odpowiedz

-3

Z pomocą Nested content_tag throws undefined method `output_buffer=` in simple helper skończyło się z poniższym rozwiązania inspirowane przez 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 %> 

Używanie output_buffer bezpośrednio i prawdopodobnie wymyślania koła kod wygląda

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 
2

Myślę, że były pewne zmiany w tym około 3,0, ale w poprzednich wersjach Sztuką było przejść self:

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

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

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

Nie jestem pewien, czy to jeszcze jak to się robi w szynach 3.

Inną rzeczą, o której należy pamiętać, aby kod działał, jest zapisanie wyniku wewnętrznego tagu content_tag gdzieś, tak jak przy each zawartość jest generowana, a następnie odrzucana. Jednym z możliwych rozwiązań:

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

Przechodząc siebie na stole pomógł, ale okazało się, że trudno zrozumieć/odczytu przekazywanie jako podwójny blok do wstrzyknięcia. – orjan

57

actionView :: Base był wbudowany moduł kontekście, który udostępnia metody output_buffer() i output_buffer = ().

Więc można rozwiązać problemu albo poprzez swoją klasę zrobić:

include ActionView::Context 

Albo jeszcze prościej:

attr_accessor :output_buffer 
Powiązane problemy