view_component 2.82.0 → 3.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of view_component might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/docs/CHANGELOG.md +102 -0
- data/lib/view_component/base.rb +26 -54
- data/lib/view_component/capture_compatibility.rb +42 -0
- data/lib/view_component/collection.rb +1 -1
- data/lib/view_component/compiler.rb +0 -6
- data/lib/view_component/config.rb +9 -13
- data/lib/view_component/deprecation.rb +1 -1
- data/lib/view_component/engine.rb +12 -22
- data/lib/view_component/rails/tasks/view_component.rake +1 -1
- data/lib/view_component/slot.rb +92 -1
- data/lib/view_component/slotable.rb +348 -97
- data/lib/view_component/system_test_helpers.rb +1 -1
- data/lib/view_component/test_helpers.rb +45 -54
- data/lib/view_component/version.rb +4 -3
- data/lib/view_component.rb +2 -10
- metadata +6 -9
- data/lib/view_component/content_areas.rb +0 -56
- data/lib/view_component/polymorphic_slots.rb +0 -103
- data/lib/view_component/slot_v2.rb +0 -98
- data/lib/view_component/slotable_v2.rb +0 -391
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2171ee963d59844894858309db964f092fb423bc4828a3bccbc917608502278
|
4
|
+
data.tar.gz: aaf7c734530bf46ea0fa5e7fdad4c6efaf7325eb45970fa2bea56d6c9f9a15c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f26a04b1af1b93be44db4436d57544c182c64a1d1036a2db62cecf0bc8b12da3f7ccf11e7cb8bf88c9c915495686ddcd774cca13a5adf7353dfc678d6c7ead1
|
7
|
+
data.tar.gz: a982b51ed80dc7da05da996005b2e60ca7af576a91c5ef13cdd68698735635fb42834e7cc45d23e5cbf45326b4ab8d8b85a1e6ddb7b2967a6d1e45638c73d50a
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,6 +10,108 @@ nav_order: 5
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
## v3.0.0.rc2
|
14
|
+
|
15
|
+
Run into an issue with this release? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
16
|
+
|
17
|
+
* BREAKING: Rename `SlotV2` to `Slot` and `SlotableV2` to `Slotable`.
|
18
|
+
|
19
|
+
*Joel Hawksley*
|
20
|
+
|
21
|
+
* BREAKING: Incorporate `PolymorphicSlots` into `Slotable`. To migrate, remove any references to `PolymorphicSlots` as they are no longer necessary.
|
22
|
+
|
23
|
+
*Joel Hawksley*
|
24
|
+
|
25
|
+
* BREAKING: Rename private TestHelpers#controller, #build_controller, #request, and #preview_class to avoid conflicts. Note: While these methods were undocumented and marked as private, they was easily accessible in tests. As such, we're cautiously considering this to be a breaking change.
|
26
|
+
|
27
|
+
*Joel Hawksley*
|
28
|
+
|
29
|
+
* Avoid loading ActionView::Base during Rails initialization. Originally submitted in #1528.
|
30
|
+
|
31
|
+
*Jonathan del Strother*
|
32
|
+
|
33
|
+
* Improve documentation of known incompatibilities with Rails form helpers.
|
34
|
+
|
35
|
+
*Tobias L. Maier*
|
36
|
+
|
37
|
+
* Remove dependency on environment task from `view_component:statsetup`.
|
38
|
+
|
39
|
+
*Svetlin Simonyan*
|
40
|
+
|
41
|
+
* Add experimental `config.view_component.capture_compatibility_patch_enabled` option resolving rendering issues related to forms, capture, turbo frames, etc.
|
42
|
+
|
43
|
+
*Blake Williams*
|
44
|
+
|
45
|
+
* Add `#content?` method that indicates if content has been passed to component.
|
46
|
+
|
47
|
+
*Joel Hawksley*
|
48
|
+
|
49
|
+
* Added example of a custom preview controller.
|
50
|
+
|
51
|
+
*Graham Rogers*
|
52
|
+
|
53
|
+
* Add Krystal to list of companies using ViewComponent.
|
54
|
+
|
55
|
+
*Matt Bearman*
|
56
|
+
|
57
|
+
* Add Mon Ami to list of companies using ViewComponent.
|
58
|
+
|
59
|
+
*Ethan Lee-Tyson*
|
60
|
+
|
61
|
+
## 3.0.0.rc1
|
62
|
+
|
63
|
+
1,000+ days and 100+ releases later, the 200+ contributors to ViewComponent are proud to ship v3.0.0!
|
64
|
+
|
65
|
+
We're so grateful for all of the work of community members to get us to this release. Whether it’s filing bug reports, designing APIs in long-winded discussion threads, or writing code itself, ViewComponent is built by the community, for the community. We couldn’t be more proud of what we’re building together :heart:
|
66
|
+
|
67
|
+
This release makes the following breaking changes, many of which have long been deprecated:
|
68
|
+
|
69
|
+
* BREAKING: Remove deprecated slots setter methods. Use `with_SLOT_NAME` instead.
|
70
|
+
|
71
|
+
*Joel Hawksley*
|
72
|
+
|
73
|
+
* BREAKING: Remove deprecated SlotsV1 in favor of current SlotsV2.
|
74
|
+
|
75
|
+
*Joel Hawksley*
|
76
|
+
|
77
|
+
* BREAKING: Remove deprecated `content_areas` feature. Use Slots instead.
|
78
|
+
|
79
|
+
*Joel Hawksley*
|
80
|
+
|
81
|
+
* BREAKING: Remove deprecated support for loading ViewComponent engine manually. Make sure `require "view_component/engine"` is removed from `Gemfile`.
|
82
|
+
|
83
|
+
*Joel Hawksley*
|
84
|
+
|
85
|
+
* BREAKING: Remove deprecated `generate_*` methods. Use `generate.*` instead.
|
86
|
+
|
87
|
+
*Joel Hawksley*
|
88
|
+
|
89
|
+
* BREAKING: Remove deprecated `with_variant` method.
|
90
|
+
|
91
|
+
*Joel Hawksley*
|
92
|
+
|
93
|
+
* BREAKING: Remove deprecated `rendered_component` in favor of `rendered_content`.
|
94
|
+
|
95
|
+
*Joel Hawksley*
|
96
|
+
|
97
|
+
* BREAKING: Remove deprecated `config.preview_path` in favor of `config.preview_paths`.
|
98
|
+
|
99
|
+
*Joel Hawksley*
|
100
|
+
|
101
|
+
* BREAKING: Support Ruby 2.7+ instead of 2.4+
|
102
|
+
|
103
|
+
*Joel Hawksley*
|
104
|
+
|
105
|
+
* BREAKING: Remove deprecated `before_render_check`.
|
106
|
+
|
107
|
+
*Joel Hawksley*
|
108
|
+
|
109
|
+
* BREAKING: Change counter variable to start iterating from `0` instead of `1`.
|
110
|
+
|
111
|
+
*Frank S*
|
112
|
+
|
113
|
+
Run into an issue with this release? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
114
|
+
|
13
115
|
## 2.82.0
|
14
116
|
|
15
117
|
* Revert "Avoid loading ActionView::Base during initialization (#1528)"
|
data/lib/view_component/base.rb
CHANGED
@@ -6,11 +6,8 @@ require "view_component/collection"
|
|
6
6
|
require "view_component/compile_cache"
|
7
7
|
require "view_component/compiler"
|
8
8
|
require "view_component/config"
|
9
|
-
require "view_component/content_areas"
|
10
|
-
require "view_component/polymorphic_slots"
|
11
9
|
require "view_component/preview"
|
12
10
|
require "view_component/slotable"
|
13
|
-
require "view_component/slotable_v2"
|
14
11
|
require "view_component/translatable"
|
15
12
|
require "view_component/with_content_helper"
|
16
13
|
|
@@ -23,7 +20,7 @@ module ViewComponent
|
|
23
20
|
#
|
24
21
|
# @return [ViewComponent::Config]
|
25
22
|
def config
|
26
|
-
@config ||=
|
23
|
+
@config ||= ActiveSupport::OrderedOptions.new
|
27
24
|
end
|
28
25
|
|
29
26
|
# Replaces the entire config. You shouldn't need to use this directly
|
@@ -31,9 +28,7 @@ module ViewComponent
|
|
31
28
|
attr_writer :config
|
32
29
|
end
|
33
30
|
|
34
|
-
include ViewComponent::
|
35
|
-
include ViewComponent::PolymorphicSlots
|
36
|
-
include ViewComponent::SlotableV2
|
31
|
+
include ViewComponent::Slotable
|
37
32
|
include ViewComponent::Translatable
|
38
33
|
include ViewComponent::WithContentHelper
|
39
34
|
|
@@ -44,9 +39,6 @@ module ViewComponent
|
|
44
39
|
# For CSRF authenticity tokens in forms
|
45
40
|
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
46
41
|
|
47
|
-
class_attribute :content_areas
|
48
|
-
self.content_areas = [] # class_attribute:default doesn't work until Rails 5.2
|
49
|
-
|
50
42
|
# Config option that strips trailing whitespace in templates before compiling them.
|
51
43
|
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false
|
52
44
|
self.__vc_strip_trailing_whitespace = false # class_attribute:default doesn't work until Rails 5.2
|
@@ -66,23 +58,6 @@ module ViewComponent
|
|
66
58
|
self.__vc_original_view_context = view_context
|
67
59
|
end
|
68
60
|
|
69
|
-
# @!macro [attach] deprecated_generate_mattr_accessor
|
70
|
-
# @method generate_$1
|
71
|
-
# @deprecated Use `#generate.$1` instead. Will be removed in v3.0.0.
|
72
|
-
def self._deprecated_generate_mattr_accessor(name)
|
73
|
-
define_singleton_method("generate_#{name}".to_sym) do
|
74
|
-
generate.public_send(name)
|
75
|
-
end
|
76
|
-
define_singleton_method("generate_#{name}=".to_sym) do |value|
|
77
|
-
generate.public_send("#{name}=".to_sym, value)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
_deprecated_generate_mattr_accessor :distinct_locale_files
|
82
|
-
_deprecated_generate_mattr_accessor :locale
|
83
|
-
_deprecated_generate_mattr_accessor :sidecar
|
84
|
-
_deprecated_generate_mattr_accessor :stimulus_controller
|
85
|
-
|
86
61
|
# Entrypoint for rendering components.
|
87
62
|
#
|
88
63
|
# - `view_context`: ActionView context from calling view
|
@@ -165,14 +140,6 @@ module ViewComponent
|
|
165
140
|
#
|
166
141
|
# @return [void]
|
167
142
|
def before_render
|
168
|
-
before_render_check
|
169
|
-
end
|
170
|
-
|
171
|
-
# Called after rendering the component.
|
172
|
-
#
|
173
|
-
# @deprecated Use `#before_render` instead. Will be removed in v3.0.0.
|
174
|
-
# @return [void]
|
175
|
-
def before_render_check
|
176
143
|
# noop
|
177
144
|
end
|
178
145
|
|
@@ -265,22 +232,9 @@ module ViewComponent
|
|
265
232
|
#
|
266
233
|
# @private
|
267
234
|
def format
|
268
|
-
# Ruby 2.6 throws a warning without checking `defined?`, 2.7 doesn't
|
269
235
|
@__vc_variant if defined?(@__vc_variant)
|
270
236
|
end
|
271
237
|
|
272
|
-
# Use the provided variant instead of the one determined by the current request.
|
273
|
-
#
|
274
|
-
# @deprecated Will be removed in v3.0.0.
|
275
|
-
# @param variant [Symbol] The variant to be used by the component.
|
276
|
-
# @return [self]
|
277
|
-
def with_variant(variant)
|
278
|
-
@__vc_variant = variant
|
279
|
-
|
280
|
-
self
|
281
|
-
end
|
282
|
-
deprecate :with_variant, deprecator: ViewComponent::Deprecation
|
283
|
-
|
284
238
|
# The current request. Use sparingly as doing so introduces coupling that
|
285
239
|
# inhibits encapsulation & reuse, often making testing difficult.
|
286
240
|
#
|
@@ -289,22 +243,40 @@ module ViewComponent
|
|
289
243
|
@request ||= controller.request if controller.respond_to?(:request)
|
290
244
|
end
|
291
245
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
246
|
+
# The content passed to the component instance as a block.
|
247
|
+
#
|
248
|
+
# @return [String]
|
296
249
|
def content
|
297
250
|
@__vc_content_evaluated = true
|
298
251
|
return @__vc_content if defined?(@__vc_content)
|
299
252
|
|
300
253
|
@__vc_content =
|
301
|
-
if
|
254
|
+
if __vc_render_in_block_provided?
|
302
255
|
view_context.capture(self, &@__vc_render_in_block)
|
303
|
-
elsif
|
256
|
+
elsif __vc_content_set_by_with_content_defined?
|
304
257
|
@__vc_content_set_by_with_content
|
305
258
|
end
|
306
259
|
end
|
307
260
|
|
261
|
+
# Whether `content` has been passed to the component.
|
262
|
+
#
|
263
|
+
# @return [Boolean]
|
264
|
+
def content?
|
265
|
+
__vc_render_in_block_provided? || __vc_content_set_by_with_content_defined?
|
266
|
+
end
|
267
|
+
|
268
|
+
private
|
269
|
+
|
270
|
+
attr_reader :view_context
|
271
|
+
|
272
|
+
def __vc_render_in_block_provided?
|
273
|
+
@view_context && @__vc_render_in_block
|
274
|
+
end
|
275
|
+
|
276
|
+
def __vc_content_set_by_with_content_defined?
|
277
|
+
defined?(@__vc_content_set_by_with_content)
|
278
|
+
end
|
279
|
+
|
308
280
|
def content_evaluated?
|
309
281
|
@__vc_content_evaluated
|
310
282
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
# CaptureCompatibility is a module that patches #capture to fix issues
|
5
|
+
# related to ViewComponent and functionality that relies on `capture`
|
6
|
+
# like forms, capture itself, turbo frames, etc.
|
7
|
+
#
|
8
|
+
# This underlying incompatibility with ViewComponent and capture is
|
9
|
+
# that several features like forms keep a reference to the primary
|
10
|
+
# `ActionView::Base` instance which has its own @output_buffer. When
|
11
|
+
# `#capture` is called on the original `ActionView::Base` instance while
|
12
|
+
# evaluating a block from a ViewComponent the @output_buffer is overridden
|
13
|
+
# in the ActionView::Base instance, and *not* the component. This results
|
14
|
+
# in a double render due to `#capture` implementation details.
|
15
|
+
#
|
16
|
+
# To resolve the issue, we override `#capture` so that we can delegate
|
17
|
+
# the `capture` logic to the ViewComponent that created the block.
|
18
|
+
module CaptureCompatibility
|
19
|
+
def self.included(base)
|
20
|
+
base.class_eval do
|
21
|
+
alias_method :original_capture, :capture
|
22
|
+
end
|
23
|
+
|
24
|
+
base.prepend(InstanceMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
def capture(*args, &block)
|
29
|
+
# Handle blocks that originate from C code and raise, such as `&:method`
|
30
|
+
return original_capture(*args, &block) if block.source_location.nil?
|
31
|
+
|
32
|
+
block_context = block.binding.receiver
|
33
|
+
|
34
|
+
if block_context != self && block_context.class < ActionView::Base
|
35
|
+
block_context.original_capture(*args, &block)
|
36
|
+
else
|
37
|
+
original_capture(*args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -62,7 +62,7 @@ module ViewComponent
|
|
62
62
|
|
63
63
|
def component_options(item, iterator)
|
64
64
|
item_options = {component.collection_parameter => item}
|
65
|
-
item_options[component.collection_counter_parameter] = iterator.index
|
65
|
+
item_options[component.collection_counter_parameter] = iterator.index if component.counter_argument_present?
|
66
66
|
item_options[component.collection_iteration_parameter] = iterator.dup if component.iteration_argument_present?
|
67
67
|
|
68
68
|
@options.merge(item_options)
|
@@ -46,12 +46,6 @@ module ViewComponent
|
|
46
46
|
return false
|
47
47
|
end
|
48
48
|
|
49
|
-
if subclass_instance_methods.include?(:before_render_check)
|
50
|
-
ViewComponent::Deprecation.deprecation_warning(
|
51
|
-
"`before_render_check`", :"`before_render`"
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
49
|
if raise_errors
|
56
50
|
component_class.validate_initialization_parameters!
|
57
51
|
component_class.validate_collection_parameter!
|
@@ -23,7 +23,8 @@ module ViewComponent
|
|
23
23
|
show_previews: Rails.env.development? || Rails.env.test?,
|
24
24
|
preview_paths: default_preview_paths,
|
25
25
|
test_controller: "ApplicationController",
|
26
|
-
default_preview_layout: nil
|
26
|
+
default_preview_layout: nil,
|
27
|
+
capture_compatibility_patch_enabled: false
|
27
28
|
})
|
28
29
|
end
|
29
30
|
|
@@ -126,9 +127,6 @@ module ViewComponent
|
|
126
127
|
# The locations in which component previews will be looked up.
|
127
128
|
# Defaults to `['test/component/previews']` relative to your Rails root.
|
128
129
|
|
129
|
-
# @!attribute preview_path
|
130
|
-
# @deprecated Use #preview_paths instead. Will be removed in v3.0.0.
|
131
|
-
|
132
130
|
# @!attribute test_controller
|
133
131
|
# @return [String]
|
134
132
|
# The controller used for testing components.
|
@@ -140,6 +138,13 @@ module ViewComponent
|
|
140
138
|
# A custom default layout used for the previews index page and individual
|
141
139
|
# previews.
|
142
140
|
# Defaults to `nil`. If this is falsy, `"component_preview"` is used.
|
141
|
+
#
|
142
|
+
# @!attribute capture_compatibility_patch_enabled
|
143
|
+
# @return [Boolean]
|
144
|
+
# Enables the experimental capture compatibility patch that makes ViewComponent
|
145
|
+
# compatible with forms, capture, and other built-ins.
|
146
|
+
# previews.
|
147
|
+
# Defaults to `false`.
|
143
148
|
|
144
149
|
def default_preview_paths
|
145
150
|
return [] unless defined?(Rails.root) && Dir.exist?("#{Rails.root}/test/components/previews")
|
@@ -158,15 +163,6 @@ module ViewComponent
|
|
158
163
|
@config = self.class.defaults
|
159
164
|
end
|
160
165
|
|
161
|
-
def preview_path
|
162
|
-
preview_paths
|
163
|
-
end
|
164
|
-
|
165
|
-
def preview_path=(new_value)
|
166
|
-
ViewComponent::Deprecation.deprecation_warning("`preview_path`", :"`preview_paths`")
|
167
|
-
self.preview_paths = Array.wrap(new_value)
|
168
|
-
end
|
169
|
-
|
170
166
|
delegate_missing_to :config
|
171
167
|
|
172
168
|
private
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rails"
|
4
|
-
require "view_component/
|
4
|
+
require "view_component/config"
|
5
5
|
|
6
6
|
module ViewComponent
|
7
7
|
class Engine < Rails::Engine # :nodoc:
|
8
|
-
config.view_component = ViewComponent::
|
8
|
+
config.view_component = ViewComponent::Config.defaults
|
9
9
|
|
10
10
|
rake_tasks do
|
11
11
|
load "view_component/rails/tasks/view_component.rake"
|
@@ -14,9 +14,6 @@ module ViewComponent
|
|
14
14
|
initializer "view_component.set_configs" do |app|
|
15
15
|
options = app.config.view_component
|
16
16
|
|
17
|
-
%i[generate preview_controller preview_route show_previews_source].each do |config_option|
|
18
|
-
options[config_option] ||= ViewComponent::Base.public_send(config_option)
|
19
|
-
end
|
20
17
|
options.instrumentation_enabled = false if options.instrumentation_enabled.nil?
|
21
18
|
options.render_monkey_patch_enabled = true if options.render_monkey_patch_enabled.nil?
|
22
19
|
options.show_previews = (Rails.env.development? || Rails.env.test?) if options.show_previews.nil?
|
@@ -39,6 +36,8 @@ module ViewComponent
|
|
39
36
|
|
40
37
|
initializer "view_component.enable_instrumentation" do |app|
|
41
38
|
ActiveSupport.on_load(:view_component) do
|
39
|
+
Base.config = app.config.view_component
|
40
|
+
|
42
41
|
if app.config.view_component.instrumentation_enabled.present?
|
43
42
|
# :nocov:
|
44
43
|
ViewComponent::Base.prepend(ViewComponent::Instrumentation)
|
@@ -47,6 +46,14 @@ module ViewComponent
|
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
49
|
+
# :nocov:
|
50
|
+
initializer "view_component.enable_capture_patch" do |app|
|
51
|
+
ActiveSupport.on_load(:view_component) do
|
52
|
+
ActionView::Base.include(ViewComponent::CaptureCompatibility) if app.config.view_component.capture_compatibility_patch_enabled
|
53
|
+
end
|
54
|
+
end
|
55
|
+
# :nocov:
|
56
|
+
|
50
57
|
initializer "view_component.set_autoload_paths" do |app|
|
51
58
|
options = app.config.view_component
|
52
59
|
|
@@ -143,20 +150,3 @@ module ViewComponent
|
|
143
150
|
end
|
144
151
|
end
|
145
152
|
end
|
146
|
-
|
147
|
-
if RUBY_VERSION < "2.7.0"
|
148
|
-
ViewComponent::Deprecation.deprecation_warning("Support for Ruby versions < 2.7.0")
|
149
|
-
end
|
150
|
-
|
151
|
-
# :nocov:
|
152
|
-
unless defined?(ViewComponent::Base)
|
153
|
-
require "view_component/deprecation"
|
154
|
-
|
155
|
-
ViewComponent::Deprecation.deprecation_warning(
|
156
|
-
"Manually loading the engine",
|
157
|
-
"remove `require \"view_component/engine\"`"
|
158
|
-
)
|
159
|
-
|
160
|
-
require "view_component"
|
161
|
-
end
|
162
|
-
# :nocov:
|
data/lib/view_component/slot.rb
CHANGED
@@ -1,7 +1,98 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "view_component/with_content_helper"
|
4
|
+
|
3
5
|
module ViewComponent
|
4
6
|
class Slot
|
5
|
-
|
7
|
+
include ViewComponent::WithContentHelper
|
8
|
+
|
9
|
+
attr_writer :__vc_component_instance, :__vc_content_block, :__vc_content
|
10
|
+
|
11
|
+
def initialize(parent)
|
12
|
+
@parent = parent
|
13
|
+
end
|
14
|
+
|
15
|
+
# Used to render the slot content in the template
|
16
|
+
#
|
17
|
+
# There's currently 3 different values that may be set, that we can render.
|
18
|
+
#
|
19
|
+
# If the slot renderable is a component, the string class name of a
|
20
|
+
# component, or a function that returns a component, we render that
|
21
|
+
# component instance, returning the string.
|
22
|
+
#
|
23
|
+
# If the slot renderable is a function and returns a string, it's
|
24
|
+
# set as `@__vc_content` and is returned directly.
|
25
|
+
#
|
26
|
+
# If there is no slot renderable, we evaluate the block passed to
|
27
|
+
# the slot and return it.
|
28
|
+
def to_s
|
29
|
+
return @content if defined?(@content)
|
30
|
+
|
31
|
+
view_context = @parent.send(:view_context)
|
32
|
+
|
33
|
+
if defined?(@__vc_content_block) && defined?(@__vc_content_set_by_with_content)
|
34
|
+
raise ArgumentError.new(
|
35
|
+
"It looks like a block was provided after calling `with_content` on #{self.class.name}, " \
|
36
|
+
"which means that ViewComponent doesn't know which content to use.\n\n" \
|
37
|
+
"To fix this issue, use either `with_content` or a block."
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
@content =
|
42
|
+
if defined?(@__vc_component_instance)
|
43
|
+
@__vc_component_instance.__vc_original_view_context = @parent.__vc_original_view_context
|
44
|
+
|
45
|
+
if defined?(@__vc_content_set_by_with_content)
|
46
|
+
@__vc_component_instance.with_content(@__vc_content_set_by_with_content)
|
47
|
+
|
48
|
+
@__vc_component_instance.render_in(view_context)
|
49
|
+
elsif defined?(@__vc_content_block)
|
50
|
+
# render_in is faster than `parent.render`
|
51
|
+
@__vc_component_instance.render_in(view_context, &@__vc_content_block)
|
52
|
+
else
|
53
|
+
@__vc_component_instance.render_in(view_context)
|
54
|
+
end
|
55
|
+
elsif defined?(@__vc_content)
|
56
|
+
@__vc_content
|
57
|
+
elsif defined?(@__vc_content_block)
|
58
|
+
view_context.capture(&@__vc_content_block)
|
59
|
+
elsif defined?(@__vc_content_set_by_with_content)
|
60
|
+
@__vc_content_set_by_with_content
|
61
|
+
end
|
62
|
+
|
63
|
+
@content = @content.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
# Allow access to public component methods via the wrapper
|
67
|
+
#
|
68
|
+
# for example
|
69
|
+
#
|
70
|
+
# calling `header.name` (where `header` is a slot) will call `name`
|
71
|
+
# on the `HeaderComponent` instance.
|
72
|
+
#
|
73
|
+
# Where the component may look like:
|
74
|
+
#
|
75
|
+
# class MyComponent < ViewComponent::Base
|
76
|
+
# has_one :header, HeaderComponent
|
77
|
+
#
|
78
|
+
# class HeaderComponent < ViewComponent::Base
|
79
|
+
# def name
|
80
|
+
# @name
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
def method_missing(symbol, *args, &block)
|
86
|
+
@__vc_component_instance.public_send(symbol, *args, &block)
|
87
|
+
end
|
88
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
89
|
+
|
90
|
+
def html_safe?
|
91
|
+
to_s.html_safe?
|
92
|
+
end
|
93
|
+
|
94
|
+
def respond_to_missing?(symbol, include_all = false)
|
95
|
+
defined?(@__vc_component_instance) && @__vc_component_instance.respond_to?(symbol, include_all)
|
96
|
+
end
|
6
97
|
end
|
7
98
|
end
|