komposable / komponent

An opinionated way of organizing front-end code in Ruby on Rails, based on components

Home Page:http://komponent.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rails 6 - undefined method `view_renderer='

agungyuliaji opened this issue · comments

How to reproduce:

  • use rails 6 6.0.0.beta3
  • install komponet gem
  • just follow button generate example from Readme
  • render the button componet into the view, component 'button'

Hi @agungyuliaji

which version of Komponent are you using?

Thanks in advance.

Hi @Spone
it's ver. 2.2.0

Can you try with 3.0.0.beta1?

still same with 3.0.0.beta1, the core problem is, view_renderer= is not exist
i've updated my PR, fix the test run, #134

but now I think maybe this is a little far away (since rails 6 is beta),
maybe we can close this issue,
and I will use the monkeypatch mode for my issue.

thanks bro 👊

Thanks for the feedback. I'll keep the issue open because it's weird our tests haven't detected the issue. I reopened #118 to update our tests to the new beta3.

Our tests were actually not run on Rails 6 🤦‍♂️

I managed to reproduce the issue in the tests: https://travis-ci.org/komposable/komponent/jobs/511340428

Same problem here :D It should also be good if it moves and renames javascript to frontend and also copy channels and other folders

Okay, temporary solution.
Clone the repo and move it to the application's lib folder
update Gemfile and add

gem 'komponent', path: './lib/komponent'

Edit component_renderer file as below or just replace "view_renderer" instance variables to "render"

# frozen_string_literal: true

module Komponent
  class ComponentRenderer
    include ActionView::Helpers::CaptureHelper

    attr_accessor :output_buffer
    attr_reader :context

    def initialize(controller, view_flow = nil)
      @context = controller.view_context.dup
      @render = @context.view_renderer
      @lookup_context = @render.lookup_context = @render.lookup_context.dup
      @view_flow = view_flow
    end

    def render(component, locals = {}, options = {}, &block)
      cached = options.delete(:cached)
      if cached

        cached_block = block ? block.call : nil
        key = [component, locals, options, cached_block].to_s
        cache_key = Digest::SHA1.hexdigest(key)

        Rails.cache.fetch(cache_key) do
          _render(component, locals, options, &block)
        end
      else
        _render(component, locals, options, &block)
      end
    end

    private

    def _render(component, locals = {}, options = {}, &block)
      parts = component.split("/")
      component_name = parts.join("_")

      component_module_path = resolved_component_path(component)
        .join("#{component_name}_component")
      require_dependency(component_module_path)
      component_module = "#{component_name}_component".camelize.constantize

      @context.view_flow = @view_flow if @view_flow
      @context.class_eval { prepend component_module }
      @context.class_eval { prepend Komponent::Translation }

      @lookup_context.prefixes = ["components/#{component}"]

      @context.instance_eval do
        if component_module.respond_to?(:properties)
          locals = locals.dup
          component_module.properties.each do |name, options|
            unless locals.has_key?(name)
              if options.has_key?(:default)
                locals[name] = options[:default]
              elsif options[:required]
                raise "Missing required component parameter: #{name}"
              end
            end
          end
        end

        locals.each do |name, value|
          instance_variable_set(:"@#{name}", locals[name])
        end

        define_singleton_method(:properties) { locals }
        define_singleton_method(:block_given_to_component?) { block_given? }
        define_singleton_method(:block_given_to_component) { block }
      end

      @context.render("components/#{component}/#{parts.join('_')}", &block)
    end

    def resolved_component_path(component)
      Komponent::ComponentPathResolver.new.resolve(component)
    end
  end
end

Works for me on both 5.1.x and 6.0rc

Hi! Maybe it would be better to create separate branch with this patch?