Class: ViewComponent::Slot
- Inherits:
-
Object
- Object
- ViewComponent::Slot
- Includes:
- WithContentHelper
- Defined in:
- lib/view_component/slot.rb
Instance Attribute Summary collapse
-
#__vc_component_instance ⇒ Object
writeonly
Sets the attribute __vc_component_instance.
-
#__vc_content ⇒ Object
writeonly
Sets the attribute __vc_content.
-
#__vc_content_block ⇒ Object
writeonly
Sets the attribute __vc_content_block.
Instance Method Summary collapse
- #content? ⇒ Boolean
- #html_safe? ⇒ Boolean
-
#initialize(parent) ⇒ Slot
constructor
A new instance of Slot.
-
#method_missing(symbol, *args, &block) ⇒ Object
Allow access to public component methods via the wrapper.
- #respond_to_missing?(symbol, include_all = false) ⇒ Boolean
-
#to_s ⇒ Object
Used to render the slot content in the template.
- #with_content(args) ⇒ Object
Constructor Details
#initialize(parent) ⇒ Slot
Returns a new instance of Slot.
11 12 13 |
# File 'lib/view_component/slot.rb', line 11 def initialize(parent) @parent = parent end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args, &block) ⇒ Object
Allow access to public component methods via the wrapper
for example
calling ‘header.name` (where `header` is a slot) will call `name` on the `HeaderComponent` instance.
Where the component may look like:
class MyComponent < ViewComponent::Base
has_one :header, HeaderComponent
class HeaderComponent < ViewComponent::Base
def name
@name
end
end
end
104 105 106 |
# File 'lib/view_component/slot.rb', line 104 def method_missing(symbol, *args, &block) @__vc_component_instance.public_send(symbol, *args, &block) end |
Instance Attribute Details
#__vc_component_instance=(value) ⇒ Object (writeonly)
Sets the attribute __vc_component_instance
9 10 11 |
# File 'lib/view_component/slot.rb', line 9 def __vc_component_instance=(value) @__vc_component_instance = value end |
#__vc_content=(value) ⇒ Object (writeonly)
Sets the attribute __vc_content
9 10 11 |
# File 'lib/view_component/slot.rb', line 9 def __vc_content=(value) @__vc_content = value end |
#__vc_content_block=(value) ⇒ Object (writeonly)
Sets the attribute __vc_content_block
9 10 11 |
# File 'lib/view_component/slot.rb', line 9 def __vc_content_block=(value) @__vc_content_block = value end |
Instance Method Details
#content? ⇒ Boolean
15 16 17 18 19 20 21 22 |
# File 'lib/view_component/slot.rb', line 15 def content? return true if defined?(@__vc_content) && @__vc_content.present? return true if defined?(@__vc_content_set_by_with_content) && @__vc_content_set_by_with_content.present? return true if defined?(@__vc_content_block) && @__vc_content_block.present? return false if !__vc_component_instance? @__vc_component_instance.content? end |
#html_safe? ⇒ Boolean
109 110 111 112 113 |
# File 'lib/view_component/slot.rb', line 109 def html_safe? # :nocov: to_s.html_safe? # :nocov: end |
#respond_to_missing?(symbol, include_all = false) ⇒ Boolean
115 116 117 |
# File 'lib/view_component/slot.rb', line 115 def respond_to_missing?(symbol, include_all = false) __vc_component_instance? && @__vc_component_instance.respond_to?(symbol, include_all) end |
#to_s ⇒ Object
Used to render the slot content in the template
There’s currently 3 different values that may be set, that we can render.
If the slot renderable is a component, the string class name of a component, or a function that returns a component, we render that component instance, returning the string.
If the slot renderable is a function and returns a string, it’s set as ‘@__vc_content` and is returned directly.
If there is no slot renderable, we evaluate the block passed to the slot and return it.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/view_component/slot.rb', line 45 def to_s return @content if defined?(@content) view_context = @parent.send(:view_context) if defined?(@__vc_content_block) && defined?(@__vc_content_set_by_with_content) raise DuplicateSlotContentError.new(self.class.name) end @content = if __vc_component_instance? @__vc_component_instance.__vc_original_view_context = @parent.__vc_original_view_context if defined?(@__vc_content_block) # render_in is faster than `parent.render` @__vc_component_instance.render_in(view_context) do |*args| return @__vc_content_block.call(*args) if @__vc_content_block&.source_location.nil? block_context = @__vc_content_block.binding.receiver if block_context.class < ActionView::Base block_context.capture(*args, &@__vc_content_block) else @__vc_content_block.call(*args) end end else @__vc_component_instance.render_in(view_context) end elsif defined?(@__vc_content) @__vc_content elsif defined?(@__vc_content_block) view_context.capture(&@__vc_content_block) elsif defined?(@__vc_content_set_by_with_content) @__vc_content_set_by_with_content end @content = @content.to_s end |
#with_content(args) ⇒ Object
24 25 26 27 28 29 30 |
# File 'lib/view_component/slot.rb', line 24 def with_content(args) if __vc_component_instance? @__vc_component_instance.with_content(args) else super end end |