lib/action_view/component/base.rb in actionview-component-1.6.0 vs lib/action_view/component/base.rb in actionview-component-1.6.1

- old
+ new

@@ -1,18 +1,15 @@ # frozen_string_literal: true -require "active_model" -require "action_view" require "active_support/configurable" -require_relative "preview" module ActionView module Component class Base < ActionView::Base include ActiveModel::Validations include ActiveSupport::Configurable - include ActionView::Component::Previews + include ActionView::Component::Previewable delegate :form_authenticity_token, :protect_against_forgery?, to: :helpers # Entrypoint for rendering components. Called by ActionView::Base#render. # @@ -111,28 +108,42 @@ else "call" end end + def has_initializer? + self.instance_method(:initialize).owner == self + end + def source_location # Require #initialize to be defined so that we can use # method#source_location to look up the file name # of the component. # # If we were able to only support Ruby 2.7+, # We could just use Module#const_source_location, # rendering this unnecessary. - raise NotImplementedError.new("#{self} must implement #initialize.") unless self.instance_method(:initialize).owner == self + raise NotImplementedError.new("#{self} must implement #initialize.") unless has_initializer? instance_method(:initialize).source_location[0] end + def eager_load! + self.descendants.each do |descendant| + descendant.compile if descendant.has_initializer? + end + end + + def compiled? + @compiled && ActionView::Base.cache_template_loading + end + # Compile templates to instance methods, assuming they haven't been compiled already. # We could in theory do this on app boot, at least in production environments. # Right now this just compiles the first time the component is rendered. def compile - return if @compiled && ActionView::Base.cache_template_loading + return if compiled? validate_templates templates.each do |template| class_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -159,16 +170,22 @@ source_location end private + def matching_views_in_source_location + (Dir["#{source_location.sub(/#{File.extname(source_location)}$/, '')}.*{#{ActionView::Template.template_handler_extensions.join(',')}}"] - [source_location]) + end + def templates @templates ||= - (Dir["#{source_location.sub(/#{File.extname(source_location)}$/, '')}.*{#{ActionView::Template.template_handler_extensions.join(',')}}"] - [source_location]).each_with_object([]) do |path, memo| + matching_views_in_source_location.each_with_object([]) do |path, memo| + pieces = File.basename(path).split(".") + memo << { path: path, - variant: path.split(".").second.split("+")[1]&.to_sym, - handler: path.split(".").last + variant: pieces.second.split("+")[1]&.to_sym, + handler: pieces.last } end end def validate_templates