module ViewComponent::Slotable
def with_slot(*slot_names, collection: false, class_name: nil)
class_name: "Header" # class name string, used to instantiate Slot
collection: true|false,
:header,
with_slot(
support initializing slots as:
def with_slot(*slot_names, collection: false, class_name: nil) ViewComponent::Deprecation.warn( "`with_slot` is deprecated and will be removed in ViewComponent v3.0.0.\n" \ "Use the new slots API (https://viewcomponent.org/guide/slots.html) instead." ) slot_names.each do |slot_name| # Ensure slot_name isn't already declared if slots.key?(slot_name) raise ArgumentError.new("#{slot_name} slot declared multiple times") end # Ensure slot name isn't :content if slot_name == :content raise ArgumentError.new ":content is a reserved slot name. Please use another name, such as ':body'" end # Set the name of the method used to access the Slot(s) accessor_name = if collection # If Slot is a collection, set the accessor # name to the pluralized form of the slot name # For example: :tab => :tabs ActiveSupport::Inflector.pluralize(slot_name) else slot_name end instance_variable_name = "@#{accessor_name}" # If the slot is a collection, define an accesor that defaults to an empty array if collection class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{accessor_name} content unless content_evaluated? # ensure content is loaded so slots will be defined #{instance_variable_name} ||= [] end RUBY else class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{accessor_name} content unless content_evaluated? # ensure content is loaded so slots will be defined #{instance_variable_name} if defined?(#{instance_variable_name}) end RUBY end # Default class_name to ViewComponent::Slot class_name = "ViewComponent::Slot" unless class_name.present? # Register the slot on the component slots[slot_name] = { class_name: class_name, instance_variable_name: instance_variable_name, collection: collection } end end