view_component 3.23.2 → 4.0.0.alpha1
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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/view_component/preview_actions.rb +2 -9
- data/app/controllers/view_components_system_test_controller.rb +17 -20
- data/app/views/test_mailer/test_asset_email.html.erb +1 -0
- data/app/views/view_components/preview.html.erb +1 -9
- data/docs/CHANGELOG.md +93 -9
- data/lib/view_component/base.rb +43 -66
- data/lib/view_component/collection.rb +11 -17
- data/lib/view_component/compiler.rb +50 -74
- data/lib/view_component/config.rb +0 -21
- data/lib/view_component/deprecation.rb +1 -1
- data/lib/view_component/engine.rb +3 -82
- data/lib/view_component/errors.rb +16 -22
- data/lib/view_component/inline_template.rb +2 -3
- data/lib/view_component/instrumentation.rb +4 -10
- data/lib/view_component/preview.rb +3 -10
- data/lib/view_component/request_details.rb +30 -0
- data/lib/view_component/slot.rb +2 -5
- data/lib/view_component/slotable.rb +30 -37
- data/lib/view_component/system_test_helpers.rb +1 -2
- data/lib/view_component/template.rb +106 -83
- data/lib/view_component/test_helpers.rb +22 -42
- data/lib/view_component/translatable.rb +24 -23
- data/lib/view_component/use_helpers.rb +3 -4
- data/lib/view_component/version.rb +4 -4
- data/lib/view_component.rb +0 -1
- metadata +68 -211
- data/app/assets/vendor/prism.css +0 -4
- data/app/assets/vendor/prism.min.js +0 -12
- data/app/helpers/preview_helper.rb +0 -85
- data/app/views/view_components/_preview_source.html.erb +0 -17
- data/lib/rails/generators/abstract_generator.rb +0 -56
- data/lib/rails/generators/component/component_generator.rb +0 -67
- data/lib/rails/generators/component/templates/component.rb.tt +0 -16
- data/lib/rails/generators/erb/component_generator.rb +0 -33
- data/lib/rails/generators/erb/templates/component.html.erb.tt +0 -1
- data/lib/rails/generators/haml/component_generator.rb +0 -22
- data/lib/rails/generators/haml/templates/component.html.haml.tt +0 -1
- data/lib/rails/generators/locale/component_generator.rb +0 -46
- data/lib/rails/generators/preview/component_generator.rb +0 -39
- data/lib/rails/generators/preview/templates/component_preview.rb.tt +0 -9
- data/lib/rails/generators/rspec/component_generator.rb +0 -31
- data/lib/rails/generators/rspec/templates/component_spec.rb.tt +0 -15
- data/lib/rails/generators/slim/component_generator.rb +0 -22
- data/lib/rails/generators/slim/templates/component.html.slim.tt +0 -1
- data/lib/rails/generators/stimulus/component_generator.rb +0 -44
- data/lib/rails/generators/stimulus/templates/component_controller.js.tt +0 -7
- data/lib/rails/generators/stimulus/templates/component_controller.ts.tt +0 -9
- data/lib/rails/generators/tailwindcss/component_generator.rb +0 -11
- data/lib/rails/generators/tailwindcss/templates/component.html.erb.tt +0 -1
- data/lib/rails/generators/test_unit/component_generator.rb +0 -20
- data/lib/rails/generators/test_unit/templates/component_test.rb.tt +0 -12
- data/lib/view_component/component_error.rb +0 -6
- data/lib/view_component/rails/tasks/view_component.rake +0 -20
- data/lib/view_component/render_component_helper.rb +0 -10
- data/lib/view_component/render_component_to_string_helper.rb +0 -9
- data/lib/view_component/render_monkey_patch.rb +0 -13
- data/lib/view_component/render_to_string_monkey_patch.rb +0 -13
- data/lib/view_component/rendering_component_helper.rb +0 -9
- data/lib/view_component/rendering_monkey_patch.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8c0d5be4a21f5c14ed5447caeaffb8d6e51397a1ec786f573bc58d9486fc747
|
4
|
+
data.tar.gz: 332de180e52e1b5eae806fb47e9d1dea4a32374cdf63a0642ca69d3661e4c802
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e298e8e18d147034b30fb60f32a7bbf5d5f42d1235d5947cfeba4e3e1b8ad65a57379f3a3fb361ba7ffdec727687689ceb98b4b893e038a16ea5496663d4423a
|
7
|
+
data.tar.gz: f6e8f8956abde8eac1e4825c09a2554dde1dd80efac74ba541210e2fe663e23399ddc01289ca44dee21e6c3551b32117b88444d9795fbb450b02639ebc9fadbf
|
@@ -10,18 +10,11 @@ module ViewComponent
|
|
10
10
|
around_action :set_locale, only: :previews
|
11
11
|
before_action :require_local!, unless: :show_previews?
|
12
12
|
|
13
|
-
content_security_policy(false)
|
13
|
+
content_security_policy(false)
|
14
14
|
|
15
15
|
# Including helpers here ensures that we're loading the
|
16
16
|
# latest version of helpers if code-reloading is enabled
|
17
|
-
if include_all_helpers
|
18
|
-
helper :all
|
19
|
-
else
|
20
|
-
# :nocov:
|
21
|
-
# Always provide the #view_source helper
|
22
|
-
helper PreviewHelper
|
23
|
-
# :nocov:
|
24
|
-
end
|
17
|
+
helper :all if include_all_helpers
|
25
18
|
end
|
26
19
|
|
27
20
|
def index
|
@@ -1,30 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ViewComponentsSystemTestController < ActionController::Base # :nodoc:
|
4
|
-
|
5
|
-
|
4
|
+
if Rails.env.test?
|
5
|
+
before_action :validate_file_path
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def system_test_entrypoint
|
12
|
-
render file: @path
|
13
|
-
end
|
7
|
+
def self.temp_dir
|
8
|
+
@_tmpdir ||= FileUtils.mkdir_p("./tmp/view_components/").first
|
9
|
+
end
|
14
10
|
|
15
|
-
|
11
|
+
def system_test_entrypoint
|
12
|
+
render file: @path
|
13
|
+
end
|
16
14
|
|
17
|
-
|
18
|
-
raise ViewComponent::SystemTestControllerOnlyAllowedInTestError unless Rails.env.test?
|
19
|
-
end
|
15
|
+
private
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
# Ensure that the file path is valid and doesn't target files outside
|
18
|
+
# the expected directory (e.g. via a path traversal or symlink attack)
|
19
|
+
def validate_file_path
|
20
|
+
base_path = ::File.realpath(self.class.temp_dir)
|
21
|
+
@path = ::File.realpath(params.permit(:file)[:file], base_path)
|
22
|
+
unless @path.start_with?(base_path)
|
23
|
+
raise ViewComponent::SystemTestControllerNefariousPathError
|
24
|
+
end
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render AssetComponent.new %>
|
@@ -1,13 +1,5 @@
|
|
1
1
|
<% if @render_args[:component] %>
|
2
|
-
|
3
|
-
<%= render(@render_args[:component], @render_args[:args], &@render_args[:block]) %>
|
4
|
-
<% else %>
|
5
|
-
<%= render_component(@render_args[:component], &@render_args[:block]) %>
|
6
|
-
<% end %>
|
2
|
+
<%= render(@render_args[:component], @render_args[:args], &@render_args[:block]) %>
|
7
3
|
<% else %>
|
8
4
|
<%= render template: @render_args[:template], locals: @render_args[:locals] || {} %>
|
9
5
|
<% end %>
|
10
|
-
|
11
|
-
<% if ViewComponent::Base.config.show_previews_source %>
|
12
|
-
<%= preview_source %>
|
13
|
-
<% end %>
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,23 +10,107 @@ nav_order: 6
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
-
##
|
13
|
+
## 4.0.0
|
14
14
|
|
15
|
-
|
15
|
+
Almost six years after releasing [v1.0.0](https://github.com/ViewComponent/view_component/releases/tag/v1.0.0), we're proud to ship ViewComponent 4. This release marks a shift towards a Long Term Support model for the project, having reached significant feature maturity. While contributions are always welcome, we're unlikely to accept further breaking changes or major feature additions.
|
16
16
|
|
17
|
-
|
17
|
+
This release makes the following breaking changes:
|
18
18
|
|
19
|
-
|
19
|
+
* BREAKING: `--inline` generator option now generates inline template. Use `--call` to generate `#call` method.
|
20
20
|
|
21
|
-
*
|
21
|
+
*Joel Hawksley*
|
22
22
|
|
23
|
-
|
23
|
+
* BREAKING: Remove `use_deprecated_instrumentation_name` configuration option. Events will always use `render.view_component` name.
|
24
|
+
|
25
|
+
*Joel Hawksley*
|
26
|
+
|
27
|
+
* BREAKING: Remove `preview_source` functionality. Consider using [Lookbook](https://lookbook.build/) instead.
|
28
|
+
|
29
|
+
*Joel Hawksley*
|
30
|
+
|
31
|
+
* BREAKING: Use `Nokogiri::HTML5` instead of `Nokogiri::HTML4` for test helpers.
|
32
|
+
|
33
|
+
*Noah Silvera*, *Joel Hawksley*
|
34
|
+
|
35
|
+
* BREAKING: Move generators to a ViewComponent namespace.
|
36
|
+
|
37
|
+
Before, ViewComponent generators pollute the generator namespace with a bunch of top level items, and claim the generic "component" name.
|
38
|
+
|
39
|
+
Now, generators live in a "view_component" module/namespace, so what was before `rails g
|
40
|
+
component` is now `rails g view_component:component`.
|
41
|
+
|
42
|
+
*Paul Sadauskas*
|
43
|
+
|
44
|
+
* BREAKING: Require [non-EOL](https://endoflife.date/rails) Rails (`>= 7.1.0`).
|
45
|
+
|
46
|
+
*Joel Hawksley*
|
47
|
+
|
48
|
+
* BREAKING: Require [non-EOL](https://www.ruby-lang.org/en/downloads/branches/) Ruby (`>= 3.2.0`).
|
49
|
+
|
50
|
+
*Joel Hawksley*
|
51
|
+
|
52
|
+
* BREAKING: Remove `render_component` and `render` monkey patch configured with `render_monkey_patch_enabled`.
|
53
|
+
|
54
|
+
*Joel Hawksley*
|
55
|
+
|
56
|
+
* BREAKING: Remove support for variant names containing `.` to be consistent with Rails.
|
57
|
+
|
58
|
+
*Stephen Nelson*
|
59
|
+
|
60
|
+
* BREAKING: Use ActionView's `lookup_context` for picking templates instead of the request format.
|
61
|
+
|
62
|
+
3.15 added support for using templates that match the request format, i.e. if `/resource.csv` is requested then
|
63
|
+
ViewComponents would pick `_component.csv.erb` over `_component.html.erb`.
|
64
|
+
|
65
|
+
With this release, the request format is no longer considered and instead ViewComponent will use the Rails logic
|
66
|
+
for picking the most appropriate template type, i.e. the csv template will be used if it matches the `Accept` header
|
67
|
+
or because the controller uses a `respond_to` block to pick the response format.
|
68
|
+
|
69
|
+
*Stephen Nelson*
|
24
70
|
|
25
|
-
|
71
|
+
* BREAKING: Rename internal methods to have `__vc_` prefix if they shouldn't be used by consumers. Make internal constants private. Make `Collection#components`, `Slotable#register_polymorphic_slot` private. Remove unused `ComponentError` class.
|
72
|
+
|
73
|
+
*Joel Hawksley*
|
74
|
+
|
75
|
+
* Fix bug where request-aware helpers did not work outside of the request context.
|
76
|
+
|
77
|
+
*Joel Hawksley*, *Stephen Nelson*
|
78
|
+
|
79
|
+
* `ViewComponentsSystemTestController` should not be useable outside of test environment
|
80
|
+
|
81
|
+
*Joel Hawksley*, *Stephen Nelson*
|
82
|
+
|
83
|
+
* Remove unnecessary ENABLE_RELOADING test suite flag.
|
84
|
+
|
85
|
+
*Joel Hawksley*
|
86
|
+
|
87
|
+
* Add test coverage for uncovered code.
|
88
|
+
|
89
|
+
*Joel Hawksley*
|
90
|
+
|
91
|
+
* Remove unnecessary `#format` methods that returned `nil`.
|
92
|
+
|
93
|
+
*Joel Hawksley*
|
94
|
+
|
95
|
+
* Clean up project dependencies, relaxing versions of development gems.
|
96
|
+
|
97
|
+
*Joel Hawksley*
|
98
|
+
|
99
|
+
* Test against `turbo-rails` `v2`.
|
100
|
+
|
101
|
+
*Joel Hawksley*
|
102
|
+
|
103
|
+
* Test against `rspec-rails` `v7`.
|
104
|
+
|
105
|
+
*Joel Hawksley*
|
106
|
+
|
107
|
+
* Remove unnecessary usage of `ruby2_keywords`.
|
108
|
+
|
109
|
+
*Joel Hawksley*
|
26
110
|
|
27
|
-
*
|
111
|
+
* Remove unnecessary `respond_to` checks.
|
28
112
|
|
29
|
-
*Joel Hawksley
|
113
|
+
*Tiago Menegaz*, *Joel Hawksley*
|
30
114
|
|
31
115
|
* Do not include internal `DocsBuilderComponent` or `YARD::MattrAccessorHandler` in published gem.
|
32
116
|
|
data/lib/view_component/base.rb
CHANGED
@@ -9,6 +9,7 @@ require "view_component/config"
|
|
9
9
|
require "view_component/errors"
|
10
10
|
require "view_component/inline_template"
|
11
11
|
require "view_component/preview"
|
12
|
+
require "view_component/request_details"
|
12
13
|
require "view_component/slotable"
|
13
14
|
require "view_component/slotable_default"
|
14
15
|
require "view_component/template"
|
@@ -25,10 +26,9 @@ module ViewComponent
|
|
25
26
|
#
|
26
27
|
# @return [ActiveSupport::OrderedOptions]
|
27
28
|
def config
|
28
|
-
module_parents.each do |
|
29
|
-
|
30
|
-
|
31
|
-
return module_parent_config if module_parent_config
|
29
|
+
module_parents.each do |m|
|
30
|
+
config = m.try(:config).try(:view_component)
|
31
|
+
return config if config
|
32
32
|
end
|
33
33
|
ViewComponent::Config.current
|
34
34
|
end
|
@@ -40,9 +40,6 @@ module ViewComponent
|
|
40
40
|
include ViewComponent::Translatable
|
41
41
|
include ViewComponent::WithContentHelper
|
42
42
|
|
43
|
-
RESERVED_PARAMETER = :content
|
44
|
-
VC_INTERNAL_DEFAULT_FORMAT = :html
|
45
|
-
|
46
43
|
# For CSRF authenticity tokens in forms
|
47
44
|
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
48
45
|
|
@@ -50,8 +47,7 @@ module ViewComponent
|
|
50
47
|
delegate :content_security_policy_nonce, to: :helpers
|
51
48
|
|
52
49
|
# Config option that strips trailing whitespace in templates before compiling them.
|
53
|
-
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false
|
54
|
-
self.__vc_strip_trailing_whitespace = false # class_attribute:default doesn't work until Rails 5.2
|
50
|
+
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false, default: false
|
55
51
|
|
56
52
|
attr_accessor :__vc_original_view_context
|
57
53
|
|
@@ -68,6 +64,8 @@ module ViewComponent
|
|
68
64
|
self.__vc_original_view_context = view_context
|
69
65
|
end
|
70
66
|
|
67
|
+
using RequestDetails
|
68
|
+
|
71
69
|
# Entrypoint for rendering components.
|
72
70
|
#
|
73
71
|
# - `view_context`: ActionView context from calling view
|
@@ -77,7 +75,7 @@ module ViewComponent
|
|
77
75
|
#
|
78
76
|
# @return [String]
|
79
77
|
def render_in(view_context, &block)
|
80
|
-
self.class.
|
78
|
+
self.class.__vc_compile(raise_errors: true)
|
81
79
|
|
82
80
|
@view_context = view_context
|
83
81
|
self.__vc_original_view_context ||= view_context
|
@@ -86,22 +84,18 @@ module ViewComponent
|
|
86
84
|
|
87
85
|
@lookup_context ||= view_context.lookup_context
|
88
86
|
|
89
|
-
# required for path helpers in older Rails versions
|
90
|
-
@view_renderer ||= view_context.view_renderer
|
91
|
-
|
92
87
|
# For content_for
|
93
88
|
@view_flow ||= view_context.view_flow
|
94
89
|
|
95
90
|
# For i18n
|
96
91
|
@virtual_path ||= virtual_path
|
97
92
|
|
98
|
-
#
|
99
|
-
@
|
93
|
+
# Describes the inferred request constraints (locales, formats, variants)
|
94
|
+
@__vc_requested_details ||= @lookup_context.vc_requested_details
|
100
95
|
|
101
96
|
# For caching, such as #cache_if
|
102
97
|
@current_template = nil unless defined?(@current_template)
|
103
98
|
old_current_template = @current_template
|
104
|
-
@current_template = self
|
105
99
|
|
106
100
|
if block && defined?(@__vc_content_set_by_with_content)
|
107
101
|
raise DuplicateContentError.new(self.class.name)
|
@@ -113,7 +107,7 @@ module ViewComponent
|
|
113
107
|
before_render
|
114
108
|
|
115
109
|
if render?
|
116
|
-
rendered_template = render_template_for(@
|
110
|
+
rendered_template = render_template_for(@__vc_requested_details).to_s
|
117
111
|
|
118
112
|
# Avoid allocating new string when output_preamble and output_postamble are blank
|
119
113
|
if output_preamble.blank? && output_postamble.blank?
|
@@ -161,7 +155,7 @@ module ViewComponent
|
|
161
155
|
target_render = self.class.instance_variable_get(:@__vc_ancestor_calls)[@__vc_parent_render_level]
|
162
156
|
@__vc_parent_render_level += 1
|
163
157
|
|
164
|
-
target_render.bind_call(self, @
|
158
|
+
target_render.bind_call(self, @__vc_requested_details)
|
165
159
|
ensure
|
166
160
|
@__vc_parent_render_level -= 1
|
167
161
|
end
|
@@ -206,7 +200,7 @@ module ViewComponent
|
|
206
200
|
#
|
207
201
|
# This prevents an exception when rendering a partial inside of a component that has also been rendered outside
|
208
202
|
# of the component. This is due to the partials compiled template method existing in the parent `view_context`,
|
209
|
-
#
|
203
|
+
# and not the component's `view_context`.
|
210
204
|
#
|
211
205
|
# @private
|
212
206
|
def render(options = {}, args = {}, &block)
|
@@ -254,7 +248,7 @@ module ViewComponent
|
|
254
248
|
raise e, <<~MESSAGE.chomp if view_context && e.is_a?(NameError) && helpers.respond_to?(method_name)
|
255
249
|
#{e.message}
|
256
250
|
|
257
|
-
You may be trying to call a method provided as a view helper. Did you mean `helpers.#{method_name}
|
251
|
+
You may be trying to call a method provided as a view helper. Did you mean `helpers.#{method_name}'?
|
258
252
|
MESSAGE
|
259
253
|
|
260
254
|
raise
|
@@ -274,13 +268,6 @@ module ViewComponent
|
|
274
268
|
[]
|
275
269
|
end
|
276
270
|
|
277
|
-
# For caching, such as #cache_if
|
278
|
-
#
|
279
|
-
# @private
|
280
|
-
def format
|
281
|
-
@__vc_variant if defined?(@__vc_variant)
|
282
|
-
end
|
283
|
-
|
284
271
|
# The current request. Use sparingly as doing so introduces coupling that
|
285
272
|
# inhibits encapsulation & reuse, often making testing difficult.
|
286
273
|
#
|
@@ -289,10 +276,9 @@ module ViewComponent
|
|
289
276
|
__vc_request
|
290
277
|
end
|
291
278
|
|
292
|
-
# Enables consumers to override request/@request
|
293
|
-
#
|
294
279
|
# @private
|
295
280
|
def __vc_request
|
281
|
+
# The current request (if present, as mailers/jobs/etc do not have a request)
|
296
282
|
@__vc_request ||= controller.request if controller.respond_to?(:request)
|
297
283
|
end
|
298
284
|
|
@@ -335,7 +321,7 @@ module ViewComponent
|
|
335
321
|
end
|
336
322
|
|
337
323
|
def maybe_escape_html(text)
|
338
|
-
return text if
|
324
|
+
return text if @current_template && !@current_template.html?
|
339
325
|
return text if text.blank?
|
340
326
|
|
341
327
|
if text.html_safe?
|
@@ -368,13 +354,6 @@ module ViewComponent
|
|
368
354
|
# configured on a per-test basis using `with_controller_class`.
|
369
355
|
#
|
370
356
|
|
371
|
-
# Set if render monkey patches should be included or not in Rails <6.1:
|
372
|
-
#
|
373
|
-
# ```ruby
|
374
|
-
# config.view_component.render_monkey_patch_enabled = false
|
375
|
-
# ```
|
376
|
-
#
|
377
|
-
|
378
357
|
# Path for component files
|
379
358
|
#
|
380
359
|
# ```ruby
|
@@ -523,20 +502,20 @@ module ViewComponent
|
|
523
502
|
def inherited(child)
|
524
503
|
# Compile so child will inherit compiled `call_*` template methods that
|
525
504
|
# `compile` defines
|
526
|
-
|
505
|
+
__vc_compile
|
527
506
|
|
528
507
|
# Give the child its own personal #render_template_for to protect against the case when
|
529
508
|
# eager loading is disabled and the parent component is rendered before the child. In
|
530
509
|
# such a scenario, the parent will override ViewComponent::Base#render_template_for,
|
531
510
|
# meaning it will not be called for any children and thus not compile their templates.
|
532
|
-
if !child.instance_methods(false).include?(:render_template_for) && !child.
|
511
|
+
if !child.instance_methods(false).include?(:render_template_for) && !child.__vc_compiled?
|
533
512
|
child.class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
534
|
-
def render_template_for(
|
513
|
+
def render_template_for(requested_details)
|
535
514
|
# Force compilation here so the compiler always redefines render_template_for.
|
536
515
|
# This is mostly a safeguard to prevent infinite recursion.
|
537
|
-
self.class.
|
538
|
-
# .
|
539
|
-
render_template_for(
|
516
|
+
self.class.__vc_compile(raise_errors: true, force: true)
|
517
|
+
# .__vc_compile replaces this method; call the new one
|
518
|
+
render_template_for(requested_details)
|
540
519
|
end
|
541
520
|
RUBY
|
542
521
|
end
|
@@ -575,22 +554,22 @@ module ViewComponent
|
|
575
554
|
end
|
576
555
|
|
577
556
|
# @private
|
578
|
-
def
|
579
|
-
|
557
|
+
def __vc_compiled?
|
558
|
+
__vc_compiler.compiled?
|
580
559
|
end
|
581
560
|
|
582
561
|
# @private
|
583
|
-
def
|
584
|
-
|
562
|
+
def __vc_ensure_compiled
|
563
|
+
__vc_compile unless __vc_compiled?
|
585
564
|
end
|
586
565
|
|
587
566
|
# @private
|
588
|
-
def
|
589
|
-
|
567
|
+
def __vc_compile(raise_errors: false, force: false)
|
568
|
+
__vc_compiler.compile(raise_errors: raise_errors, force: force)
|
590
569
|
end
|
591
570
|
|
592
571
|
# @private
|
593
|
-
def
|
572
|
+
def __vc_compiler
|
594
573
|
@__vc_compiler ||= Compiler.new(self)
|
595
574
|
end
|
596
575
|
|
@@ -632,8 +611,8 @@ module ViewComponent
|
|
632
611
|
# is accepted, as support for collection
|
633
612
|
# rendering is optional.
|
634
613
|
# @private
|
635
|
-
def
|
636
|
-
parameter = validate_default ?
|
614
|
+
def __vc_validate_collection_parameter!(validate_default: false)
|
615
|
+
parameter = validate_default ? __vc_collection_parameter : provided_collection_parameter
|
637
616
|
|
638
617
|
return unless parameter
|
639
618
|
return if initialize_parameter_names.include?(parameter) || splatted_keyword_argument_present?
|
@@ -652,35 +631,35 @@ module ViewComponent
|
|
652
631
|
# invalid parameters that could override the framework's
|
653
632
|
# methods.
|
654
633
|
# @private
|
655
|
-
def
|
656
|
-
return unless initialize_parameter_names.include?(
|
634
|
+
def __vc_validate_initialization_parameters!
|
635
|
+
return unless initialize_parameter_names.include?(:content)
|
657
636
|
|
658
|
-
raise ReservedParameterError.new(name,
|
637
|
+
raise ReservedParameterError.new(name, :content)
|
659
638
|
end
|
660
639
|
|
661
640
|
# @private
|
662
|
-
def
|
641
|
+
def __vc_collection_parameter
|
663
642
|
provided_collection_parameter || name && name.demodulize.underscore.chomp("_component").to_sym
|
664
643
|
end
|
665
644
|
|
666
645
|
# @private
|
667
|
-
def
|
668
|
-
:"#{
|
646
|
+
def __vc_collection_counter_parameter
|
647
|
+
:"#{__vc_collection_parameter}_counter"
|
669
648
|
end
|
670
649
|
|
671
650
|
# @private
|
672
|
-
def
|
673
|
-
initialize_parameter_names.include?(
|
651
|
+
def __vc_counter_argument_present?
|
652
|
+
initialize_parameter_names.include?(__vc_collection_counter_parameter)
|
674
653
|
end
|
675
654
|
|
676
655
|
# @private
|
677
|
-
def
|
678
|
-
:"#{
|
656
|
+
def __vc_collection_iteration_parameter
|
657
|
+
:"#{__vc_collection_parameter}_iteration"
|
679
658
|
end
|
680
659
|
|
681
660
|
# @private
|
682
|
-
def
|
683
|
-
initialize_parameter_names.include?(
|
661
|
+
def __vc_iteration_argument_present?
|
662
|
+
initialize_parameter_names.include?(__vc_collection_iteration_parameter)
|
684
663
|
end
|
685
664
|
|
686
665
|
private
|
@@ -693,8 +672,6 @@ module ViewComponent
|
|
693
672
|
def initialize_parameter_names
|
694
673
|
return attribute_names.map(&:to_sym) if respond_to?(:attribute_names)
|
695
674
|
|
696
|
-
return attribute_types.keys.map(&:to_sym) if Rails::VERSION::MAJOR <= 5 && respond_to?(:attribute_types)
|
697
|
-
|
698
675
|
initialize_parameters.map(&:last)
|
699
676
|
end
|
700
677
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_view/renderer/collection_renderer"
|
3
|
+
require "action_view/renderer/collection_renderer"
|
4
4
|
|
5
5
|
module ViewComponent
|
6
6
|
class Collection
|
@@ -22,12 +22,18 @@ module ViewComponent
|
|
22
22
|
end.join(rendered_spacer(view_context)).html_safe
|
23
23
|
end
|
24
24
|
|
25
|
+
def each(&block)
|
26
|
+
components.each(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
25
31
|
def components
|
26
32
|
return @components if defined? @components
|
27
33
|
|
28
34
|
iterator = ActionView::PartialIteration.new(@collection.size)
|
29
35
|
|
30
|
-
component.
|
36
|
+
component.__vc_validate_collection_parameter!(validate_default: true)
|
31
37
|
|
32
38
|
@components = @collection.map do |item|
|
33
39
|
component.new(**component_options(item, iterator)).tap do |component|
|
@@ -36,18 +42,6 @@ module ViewComponent
|
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
39
|
-
def each(&block)
|
40
|
-
components.each(&block)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Rails expects us to define `format` on all renderables,
|
44
|
-
# but we do not know the `format` of a ViewComponent until runtime.
|
45
|
-
def format
|
46
|
-
nil
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
45
|
def initialize(component, object, spacer_component, **options)
|
52
46
|
@component = component
|
53
47
|
@collection = collection_variable(object || [])
|
@@ -64,9 +58,9 @@ module ViewComponent
|
|
64
58
|
end
|
65
59
|
|
66
60
|
def component_options(item, iterator)
|
67
|
-
item_options = {component.
|
68
|
-
item_options[component.
|
69
|
-
item_options[component.
|
61
|
+
item_options = {component.__vc_collection_parameter => item}
|
62
|
+
item_options[component.__vc_collection_counter_parameter] = iterator.index if component.__vc_counter_argument_present?
|
63
|
+
item_options[component.__vc_collection_iteration_parameter] = iterator.dup if component.__vc_iteration_argument_present?
|
70
64
|
|
71
65
|
@options.merge(item_options)
|
72
66
|
end
|