Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoMethodError: undefined method `output_buffer=' #26

Open
duleorlovic opened this issue Feb 25, 2020 · 15 comments
Open

NoMethodError: undefined method `output_buffer=' #26

duleorlovic opened this issue Feb 25, 2020 · 15 comments

Comments

@duleorlovic
Copy link

I was following traiblazer guide and stopped on the first rendering example http://trailblazer.to/guides/trailblazer/2.0/03-rails-basics.html
When I use cells-slim version 0.1.1 than I got this error in tests as well in browser

NoMethodError: undefined method `output_buffer=' for #<Venue::Cell::New:0x000055af5b301528>

I was looking at trailblazer/cells#298 but that is old case.
I'm on rails 6.0.2.1.
Quick solution is to fix version

# Gemfile
gem 'cells-slim', '0.0.6'

Can we provide some better error message so trb-newbie can overcome this situation ?
At least, we should update that guide with fixed cells-slim version.

@robbl
Copy link

robbl commented Feb 29, 2020

I get the same error message using rails 5.2.4.1 and the following versions of cells or slim:

➜ bundle list | grep 'slim\|cell'        
  * cells (4.1.7)
  * cells-rails (0.1.0)
  * cells-slim (0.1.1)
  * slim (4.0.1)

@apotonick
Copy link
Member

It's because we merged a poorly tested PR where we'd allow >= slim-4.0. They must've changed the internal buffering.

@apotonick
Copy link
Member

apotonick commented Mar 1, 2020

Any chance I can see the complete stacktrace? Alternatively, you could PR a test case, that'd be great. 🍻 You probably have to add the provoking code here in the cell: https://github.com/trailblazer/cells-slim/blob/master/test/slim_test.rb

@damien-roche
Copy link

This was driving me mad for a good hour. At least I know why now!

Stacktrace from my side:

actionview (6.0.2.2) lib/action_view/helpers/capture_helper.rb:212:in `ensure in with_output_buffer'
actionview (6.0.2.2) lib/action_view/helpers/capture_helper.rb:212:in `with_output_buffer'
actionview (6.0.2.2) lib/action_view/helpers/capture_helper.rb:45:in `capture'
actionview (6.0.2.2) lib/action_view/helpers/tag_helper.rb:273:in `content_tag'
actionview (6.0.2.2) lib/action_view/helpers/url_helper.rb:205:in `link_to'
engines/community/app/cells/community/forum/post/preview.slim:8:in `__tilt_35560460'
tilt (2.0.10) lib/tilt/template.rb:170:in `call'
tilt (2.0.10) lib/tilt/template.rb:170:in `evaluate'
tilt (2.0.10) lib/tilt/template.rb:109:in `render'
cells (4.1.7) lib/cell/view_model.rb:118:in `render_template'
cells-slim (0.1.1) lib/cell/slim.rb:8:in `render_template'
cells (4.1.7) lib/cell/view_model.rb:110:in `render_to_string'
cells (4.1.7) lib/cell/layout.rb:23:in `render_to_string'
cells (4.1.7) lib/cell/view_model.rb:104:in `render'
engines/community/app/cells/community/forum/post_cell.rb:11:in `preview'
cells (4.1.7) lib/cell/view_model.rb:114:in `render_state'
cells (4.1.7) lib/cell/caching.rb:46:in `render_state'
cells (4.1.7) lib/cell/view_model.rb:92:in `call'

@mrbongiolo
Copy link

Getting the same error when using cells-slim 0.1.1, going back to 0.0.6 fixes the issue.
Here's my stacktrace:

      NoMethodError:
        undefined method `output_buffer=' for #<Reviews::ComparisonCell:0x0000557736814ab8>
      # /usr/local/bundle/gems/haml-5.2.0/lib/haml/helpers/action_view_xss_mods.rb:7:in `with_output_buffer_with_haml_xss'
      # /usr/local/bundle/gems/haml-5.2.0/lib/haml/helpers/action_view_mods.rb:48:in `capture_with_haml'
      # /usr/local/bundle/gems/haml-5.2.0/lib/haml/helpers/action_view_mods.rb:125:in `form_tag_with_haml'
      # /usr/local/bundle/gems/haml-5.2.0/lib/haml/helpers/action_view_xss_mods.rb:20:in `form_tag_with_haml_xss'
      # ./app/cells/reviews/comparison/show.slim:9:in `__tilt_46985178061160'
      # /usr/local/bundle/gems/tilt-2.0.10/lib/tilt/template.rb:170:in `call'
      # /usr/local/bundle/gems/tilt-2.0.10/lib/tilt/template.rb:170:in `evaluate'
      # /usr/local/bundle/gems/tilt-2.0.10/lib/tilt/template.rb:109:in `render'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/view_model.rb:118:in `render_template'
      # /usr/local/bundle/gems/cells-slim-0.1.1/lib/cell/slim.rb:8:in `render_template'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/view_model.rb:110:in `render_to_string'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/layout.rb:23:in `render_to_string'
      # ./lib/patches/cell/rails.rb:25:in `render_to_string'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/view_model.rb:104:in `render'
      # ./app/cells/reviews/comparison_cell.rb:15:in `show'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/view_model.rb:114:in `render_state'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/caching.rb:46:in `render_state'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/view_model.rb:92:in `call'
      # ./lib/patches/cell/rails.rb:11:in `block in call'
      # /usr/local/bundle/gems/scout_apm-2.6.10/lib/scout_apm/tracer.rb:34:in `instrument'
      # ./lib/patches/cell/rails.rb:11:in `call'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/layout.rb:43:in `call'
      # /usr/local/bundle/gems/cells-4.1.7/lib/cell/testing.rb:47:in `call'
      # ./spec/cells/reviews/comparison_cell_spec.rb:25:in `block (5 levels) in <top (required)>'
      # /usr/local/bundle/gems/rspec-cells-0.3.5/lib/rspec/cells/example_group.rb:43:in `block (2 levels) in <module:ExampleGroup>'
      # /usr/local/bundle/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <top (required)>'
      # ------------------
      # --- Caused by: ---
      # NoMethodError:
      #   undefined method `output_buffer=' for #<Reviews::ComparisonCell:0x0000557736814ab8>
      #   Did you mean?  output_buffer
      #   /usr/local/bundle/gems/haml-5.2.0/lib/haml/helpers/action_view_xss_mods.rb:7:in `with_output_buffer_with_haml_xss'

I don't know why it's trying to call the haml lib there, all my templates are .slim.

@batamire
Copy link

batamire commented Feb 25, 2021

Any other fix possible, besides downgrading?

@apotonick
Copy link
Member

The only way to fix this properly is to talk to the nice person making slim. We spent a lot of time making output buffering completely procedural, without any magic and global state. It worked seamlessly with slim, but apparently they changed things in their core code.

Also, bit confused, why does it say haml in your stacktrace??? 😆

@mrbongiolo
Copy link

@apotonick Hey, how are you doing?
I'm not sure about haml, but probably because of rails_admin (it's the only place there are haml templates on our project). At the time I just downgraded the version to make it work and never went further to investigate the issue :/

@apotonick
Copy link
Member

Heyyyy @mrbongiolo great to see you again! Hope you're doing well! 🍻

I will have a look into slim the coming days, maybe it's easily fixable.

@richardboehme
Copy link

richardboehme commented Aug 28, 2021

Hey @apotonick! Did you had to time to look into this issue already? I fixed it for me by re-adding the rails helpers (f4f2afe) that cells-rails cells-slim had in 0.6.0. Maybe this is the problem?

Edit: Of course I mean the cells-slim gem.

@apotonick
Copy link
Member

@richardboehme ☝️ Reverting this commit does the trick? 😮

@richardboehme
Copy link

@richardboehme ☝️ Reverting this commit does the trick? 😮

Well at least it did for me. I just added

    def self.included(includer)
      includer.send :include, ActionView::Helpers::FormHelper
      includer.send :include, Helpers
    end

    module Helpers # include after AV helpers to override.
      def with_output_buffer(block_buffer=ViewModel::OutputBuffer.new)
        @output_buffer, old_buffer = block_buffer, @output_buffer
        yield
        @output_buffer = old_buffer

        block_buffer
      end

      def capture(*args)
        value = nil
        buffer = with_output_buffer { value = yield(*args) }

        return buffer.to_s if buffer.size > 0
        value # this applies for "Beachparty" string-only statements.
      end

      # From FormTagHelper. why do they escape every possible string? why?
      def form_tag_in_block(html_options, &block)
        content = capture(&block)
        form_tag_with_body(html_options, content)
      end

      def form_tag_with_body(html_options, content)
        "#{form_tag_html(html_options)}" << content.to_s << "</form>"
      end

      def form_tag_html(html_options)
        extra_tags = extra_tags_for_form(html_options)
        "#{tag(:form, html_options, true) + extra_tags}"
      end

      def tag(name = nil, options = nil, open = false, escape = true)
        super(name, options, open, true)
      end

      def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
        super(name, content_or_options_with_block, options, false, &block)
      end

      def concat(string)
        @output_buffer << string
        self
      end
    end
  end

to a module that I use in most of my cells and it worked for me. I guess the intention behind the commit is to remove the dependency to rails from this gem. So would it be possible to add these rails helpers to the cells-rails gem?

@apotonick
Copy link
Member

I remember having a lot of problems with the hacky way Rails imiplements @output_buffer behavior, we wanted to get rid of the global mutual state in Cells and Slim. Adding the Rails helpers will possibly override that. I will definitely get into touch with the Slim team but not in the coming days. 😬 Thanks for providing that fix, @robbl

@phillipoertel
Copy link

+1

@Austio
Copy link

Austio commented Sep 14, 2022

Still an issue, worked around with this

module TrailblazerCellsHelper
  # https://github.com/trailblazer/cells/blob/401025331990355cc07310c18d0c6141cb76e890/lib/cell/view_model.rb#L150
  class OutputBuffer < Array
    def encoding
      "UTF-8"
    end

    def <<(string)
      puts "OutputBuffer#<< #{string.inspect}"
      super
    end
    alias_method :safe_append=, :<<
    alias_method :append=, :<<

    def to_s # output_buffer is returned at the end of the precompiled template.
      join
    end
  end


    def with_output_buffer(block_buffer=OutputBuffer.new)
      @output_buffer, old_buffer = block_buffer, @output_buffer
      yield
      @output_buffer = old_buffer

      block_buffer
    end

    def capture(*args)
      value = nil
      buffer = with_output_buffer { value = yield(*args) }

      return buffer.to_s if buffer.size > 0
      value # this applies for "Beachparty" string-only statements.
    end

    # From FormTagHelper. why do they escape every possible string? why?
    def form_tag_in_block(html_options, &block)
      content = capture(&block)
      form_tag_with_body(html_options, content)
    end

    def form_tag_with_body(html_options, content)
      "#{form_tag_html(html_options)}" << content.to_s << "</form>"
    end

    def form_tag_html(html_options)
      extra_tags = extra_tags_for_form(html_options)
      "#{tag(:form, html_options, true) + extra_tags}"
    end

    def tag(name = nil, options = nil, open = false, escape = true)
      super(name, options, open, true)
    end

    def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
      super(name, content_or_options_with_block, options, false, &block)
    end

    def concat(string)
      @output_buffer << string
      self
    end
end

then in my form

module FormsForCells
  extend ActiveSupport::Concern

  included do
      ....
      include TrailblazerCellsHelper
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants