trailblazer / cells

View components for Ruby and Rails.
https://trailblazer.to/2.1/docs/cells.html
3.07k stars 236 forks source link

undefined method `encoding' for []:Array #265

Closed rhomeister closed 9 years ago

rhomeister commented 9 years ago

With cells v4.0.0.beta2 and HAML v4.0.6, I'm getting the following stacktrace:

NoMethodError - undefined method `encoding' for []:Array:
  actionpack (4.0.10) lib/action_view/helpers/capture_helper.rb:197:in `with_output_buffer'
  haml (4.0.3) lib/haml/helpers/action_view_xss_mods.rb:5:in `with_output_buffer_with_haml_xss'
  actionpack (4.0.10) lib/action_view/helpers/capture_helper.rb:38:in `capture'
  haml (4.0.3) lib/haml/helpers/action_view_mods.rb:59:in `capture_with_haml'
  actionpack (4.0.10) lib/action_view/helpers/tag_helper.rb:94:in `content_tag'
  haml (4.0.3) lib/haml/helpers/action_view_mods.rb:76:in `content_tag_with_haml'
  app/helpers/remote_panel_helper.rb:23:in `some_helper_method'
  app/cells/single_group_available_members/show.haml:1:in `block in singleton class'
  app/cells/single_group_available_members/show.haml:65528:in `singleton class'
  app/cells/single_group_available_members/show.haml:65526:in `__tilt_16708400'
  tilt (1.4.1) lib/tilt/template.rb:170:in `evaluate'
  tilt (1.4.1) lib/tilt/haml.rb:24:in `evaluate'
  tilt (1.4.1) lib/tilt/template.rb:103:in `render'
  cells (4.0.0.beta2) lib/cell/view_model.rb:110:in `render_to_string'
  cells (4.0.0.beta2) lib/cell/view_model.rb:105:in `render'
  app/cells/available_members_cell.rb:18:in `show'
  cells (4.0.0.beta2) lib/cell/view_model.rb:143:in `render_state'
  cells (4.0.0.beta2) lib/cell/caching.rb:47:in `render_state'
  cells (4.0.0.beta2) lib/cell/view_model.rb:124:in `call'

This problem is reproducible with a very simple setup. First, define a helper method that uses the content_tag method which is passed a block:

def some_helper_method
  content_tag(:div) { "hi" }
end

Then, use this method is in one of the HAML cell templates:

= some_helper_method

The problem does not occur if the helper is replaced by:

def some_helper_method
  content_tag(:div, "hi")
end
rhomeister commented 9 years ago

@apotonick Could you help me with this please? It's the only issue that is blocking deploy of Cells in our production environment ;)

vinett-de commented 9 years ago

+1 same problem

seuros commented 9 years ago

5 minutes .

seuros commented 9 years ago

add gem 'cells-haml'

rhomeister commented 9 years ago

Thanks! That did the trick.

incorvia commented 9 years ago

This issue still exists for ERB users..

<%= content_tag(:div) { "hi" } %>

Provides the given error:

undefined method `encoding' for []:Array
apotonick commented 9 years ago

We should add this "special behaviour" to the gems' tests, @seuros ?

lulalala commented 9 years ago

Same here for erb here:

<% form_for(model) do |f| %>
<% end %>

Should I open another issue for ERB? I am not sure if it is the same issue.

samstickland commented 9 years ago

I have the same problem for ERB when using form_for, and I've provided a very hacky fix below.

For some reason I don't get much of a stack trace, but I stepped through it with byebug and the error is in ActionView:Helpers:Capture:Helper

  def with_output_buffer(buf = nil) #:nodoc:
    unless buf
      buf = ActionView::OutputBuffer.new
      buf.force_encoding(output_buffer.encoding) if output_buffer
    end
    self.output_buffer, old_buffer = buf, output_buffer
    yield
    output_buffer
  ensure
    self.output_buffer = old_buffer
  end

Something has already defined output_buffer as an empty array, which makes it die here. Digging into the cells code shows that it's this method in ViewModel:

def output_buffer
  @output_buffer ||= []
end
attr_writer :output_buffer # TODO: test that, this breaks in MM.

This can be fixed by monkey patching like this, but it is bringing back ActionView:

module Cell
  class ViewModel < AbstractController::Base

  private
    def output_buffer
      @output_buffer ||= ActionView::OutputBuffer.new
    end
  end
end

The longer term fix would be defining output_buffer to something that supports all the methods ActionView requires.