TheNaoX/active_component

View on GitHub
lib/active_component/renderable.rb

Summary

Maintainability
A
0 mins
Test Coverage
# 
# This provides a clean implementation for rendering your template
# inside your view.
#
# <%= render_component(:view, var: var) %>
#
# In addition to that you can render a collection of components using
# the same helper method
#
# <%= render_component(:view, collection: views, as: :view)%>
#
# The :as argument helps you to provide the instance variable name that
# you defined int your component class and it will be received like that.
#
module ActiveComponent
  module Renderable

    def render_component(type, args={})
      raise_errors(type, args) if type.nil? or args.nil?

      unless args[:collection].present?
        element(type, args)
      else
        collection(type, args[:collection], args[:as], args[:locals])
      end
    end

    private

    def element(type, args)
      resource = constantize("#{type.to_s}_component").new(args)
      resource.render
    end

    def collection(type, collection, as, locals)

      error_string = "Attempting to render a collection without specifying the ':as' value"
      raise ArgumentError, error_string if as.nil?

      locals = locals || {}

      html_string = collection.map do |item|
        element(
          type,
          locals.merge(as => item)
        )
      end

      html_string.join('')
    end

    def constantize(type)
      type = type.camelize.constantize
      type
    end

    def raise_errors(type, args)
      text = "Invalid arguments. Received: #{type.class}, #{args.class}. Expected: Symbol, Hash"
      raise ArgumentError, text
    end

  end
end

ActionView::Base.send(:include, ActiveComponent::Renderable) if defined?(ActionView)