view_component 2.9.0 → 2.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of view_component might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -1
- data/README.md +151 -0
- data/lib/view_component/base.rb +31 -6
- data/lib/view_component/collection.rb +1 -1
- data/lib/view_component/engine.rb +26 -11
- data/lib/view_component/render_component_helper.rb +9 -0
- data/lib/view_component/render_component_to_string_helper.rb +9 -0
- data/lib/view_component/rendering_component_helper.rb +9 -0
- data/lib/view_component/slot.rb +7 -0
- data/lib/view_component/slotable.rb +121 -0
- data/lib/view_component/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3950532a26d2d6d1ddcf412383bfd9cde269c1f69c3d6f7f03dd4e51e7d638e2
|
4
|
+
data.tar.gz: ee2524ef62b335376287f30709e62f2d39a71e43c0f5ec9853db8142b6c8fb3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4cc6925445d3486e4c9a6ef915254cf3f28d973ad6a2876fca4fe3435b19ac273f18e89432622eaa38c8bba22ab9e9cafa07e417299dab8537848742175d1c8
|
7
|
+
data.tar.gz: 66d2a44a74a07e78f694adc4790218ee7a9d729e8cd8bb9546d154669a79d5abaa20e7d0bffa0801dfc276ef539b93d5a13dd2b4d3d3093cd8d806972d2dac81
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
# master
|
2
2
|
|
3
|
+
# 2.13.0
|
4
|
+
|
5
|
+
* Add the ability to disable the render monkey patch with `config.view_component.render_monkey_patch_enabled`. In versions of Rails < 6.1, add `render_component` and `render_component_to_string` methods which can be used for rendering components instead of `render`.
|
6
|
+
|
7
|
+
*Johannes Engl*
|
8
|
+
|
9
|
+
# 2.12.0
|
10
|
+
|
11
|
+
* Implement Slots as potential successor to Content Areas.
|
12
|
+
|
13
|
+
*Jens Ljungblad, Brian Bugh, Jon Palmer, Joel Hawksley*
|
14
|
+
|
15
|
+
# 2.11.1
|
16
|
+
|
17
|
+
* Fix kwarg warnings in Ruby 2.7.
|
18
|
+
|
19
|
+
*Joel Hawksley*
|
20
|
+
|
21
|
+
# 2.11.0
|
22
|
+
|
23
|
+
* Ensure Rails configuration is available within components.
|
24
|
+
|
25
|
+
*Trevor Broaddus*
|
26
|
+
|
27
|
+
* Fix bug where global Rails helpers are inaccessible from nested components. Before, `helpers` was pointing to parent component.
|
28
|
+
|
29
|
+
*Franco Sebregondi*
|
30
|
+
|
31
|
+
# 2.10.0
|
32
|
+
|
33
|
+
* Raise an `ArgumentError` with a helpful message when Ruby cannot parse a component class.
|
34
|
+
|
35
|
+
*Max Beizer*
|
36
|
+
|
3
37
|
# 2.9.0
|
4
38
|
|
5
39
|
* Cache components per-request in development, preventing unnecessary recompilation during a single request.
|
@@ -16,7 +50,7 @@
|
|
16
50
|
|
17
51
|
* Add `rendered_component` method to `ViewComponent::TestHelpers` which exposes the raw output of the rendered component.
|
18
52
|
|
19
|
-
|
53
|
+
*Richard Macklin*
|
20
54
|
|
21
55
|
* Support sidecar directories for views and other assets.
|
22
56
|
|
data/README.md
CHANGED
@@ -160,6 +160,133 @@ Returning:
|
|
160
160
|
</div>
|
161
161
|
```
|
162
162
|
|
163
|
+
#### Slots (experimental)
|
164
|
+
|
165
|
+
_Slots are currently under development as a successor to Content Areas. The Slot APIs should be considered unfinished and subject to breaking changes in non-major releases of ViewComponent._
|
166
|
+
|
167
|
+
Slots enable multiple blocks of content to be passed to a single ViewComponent.
|
168
|
+
|
169
|
+
Slots exist in two forms: normal slots and collection slots.
|
170
|
+
|
171
|
+
Normal slots can be rendered once per component. They expose an accessor with the name of the slot that returns an instance of `ViewComponent::Slot`, etc.
|
172
|
+
|
173
|
+
Collection slots can be rendered multiple times. They expose an accessor with the pluralized name of the slot (`#rows`), which is an Array of `ViewComponent::Slot` instances.
|
174
|
+
|
175
|
+
To learn more about the design of the Slots API, see https://github.com/github/view_component/pull/348.
|
176
|
+
|
177
|
+
##### Defining Slots
|
178
|
+
|
179
|
+
Slots are defined by the `with_slot` macro:
|
180
|
+
|
181
|
+
`with_slot :header`
|
182
|
+
|
183
|
+
To define a collection slot, add `collection: true`:
|
184
|
+
|
185
|
+
`with_slot :row, collection: true`
|
186
|
+
|
187
|
+
To define a slot with a custom class, pass `class_name`:
|
188
|
+
|
189
|
+
`with_slot :body, class_name: 'BodySlot`
|
190
|
+
|
191
|
+
Slot classes should be subclasses of `ViewComponent::Slot`.
|
192
|
+
|
193
|
+
##### Example ViewComponent with Slots
|
194
|
+
|
195
|
+
`# box_component.rb`
|
196
|
+
```ruby
|
197
|
+
class BoxComponent < ViewComponent::Base
|
198
|
+
include ViewComponent::Slotable
|
199
|
+
|
200
|
+
with_slot :body, :footer
|
201
|
+
with_slot :header, class_name: "Header"
|
202
|
+
with_slot :row, collection: true, class_name: "Row"
|
203
|
+
|
204
|
+
class Header < ViewComponent::Slot
|
205
|
+
def initialize(class_names: "")
|
206
|
+
@class_names = class_names
|
207
|
+
end
|
208
|
+
|
209
|
+
def class_names
|
210
|
+
"Box-header #{@class_names}"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
class Row < ViewComponent::Slot
|
215
|
+
def initialize(theme: :gray)
|
216
|
+
@theme = theme
|
217
|
+
end
|
218
|
+
|
219
|
+
def theme_class_name
|
220
|
+
case @theme
|
221
|
+
when :gray
|
222
|
+
"Box-row--gray"
|
223
|
+
when :hover_gray
|
224
|
+
"Box-row--hover-gray"
|
225
|
+
when :yellow
|
226
|
+
"Box-row--yellow"
|
227
|
+
when :blue
|
228
|
+
"Box-row--blue"
|
229
|
+
when :hover_blue
|
230
|
+
"Box-row--hover-blue"
|
231
|
+
else
|
232
|
+
"Box-row--gray"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
239
|
+
`# box_component.html.erb`
|
240
|
+
```erb
|
241
|
+
<div class="Box">
|
242
|
+
<% if header %>
|
243
|
+
<div class="<%= header.class_names %>">
|
244
|
+
<%= header.content %>
|
245
|
+
</div>
|
246
|
+
<% end %>
|
247
|
+
<% if body %>
|
248
|
+
<div class="Box-body">
|
249
|
+
<%= body.content %>
|
250
|
+
</div>
|
251
|
+
<% end %>
|
252
|
+
<% if rows.any? %>
|
253
|
+
<ul>
|
254
|
+
<% rows.each do |row| %>
|
255
|
+
<li class="Box-row <%= row.theme_class_name %>">
|
256
|
+
<%= row.content %>
|
257
|
+
</li>
|
258
|
+
<% end %>
|
259
|
+
</ul>
|
260
|
+
<% end %>
|
261
|
+
<% if footer %>
|
262
|
+
<div class="Box-footer">
|
263
|
+
<%= footer %>
|
264
|
+
</div>
|
265
|
+
<% end %>
|
266
|
+
</div>
|
267
|
+
```
|
268
|
+
|
269
|
+
`# index.html.erb`
|
270
|
+
```erb
|
271
|
+
<%= render(BoxComponent.new) do |component| %>
|
272
|
+
<% component.slot(:header, class_names: "my-class-name") do %>
|
273
|
+
This is my header!
|
274
|
+
<% end %>
|
275
|
+
<% component.slot(:body) do %>
|
276
|
+
This is the body.
|
277
|
+
<% end %>
|
278
|
+
<% component.slot(:row) do %>
|
279
|
+
Row one
|
280
|
+
<% end %>
|
281
|
+
<% component.slot(:row, theme: :yellow) do %>
|
282
|
+
Yellow row
|
283
|
+
<% end %>
|
284
|
+
<% component.slot(:footer) do %>
|
285
|
+
This is the footer.
|
286
|
+
<% end %>
|
287
|
+
<% end %>
|
288
|
+
```
|
289
|
+
|
163
290
|
### Inline Component
|
164
291
|
|
165
292
|
ViewComponents can render without a template file, by defining a `call` method:
|
@@ -584,6 +711,18 @@ To use component previews:
|
|
584
711
|
config.view_component.preview_path = "#{Rails.root}/spec/components/previews"
|
585
712
|
```
|
586
713
|
|
714
|
+
### Disabling the render monkey patch (Rails < 6.1)
|
715
|
+
|
716
|
+
In order to [avoid conflicts](https://github.com/github/view_component/issues/288) between ViewComponent and other gems that also monkey patch the `render` method, it is possible to configure ViewComponent to not include the render monkey patch:
|
717
|
+
|
718
|
+
`config.view_component.render_monkey_patch_enabled = false # defaults to true`
|
719
|
+
|
720
|
+
With the monkey patch disabled, use `render_component` (or `render_component_to_string`) instead:
|
721
|
+
|
722
|
+
```
|
723
|
+
<%= render_component Component.new(message: "bar") %>
|
724
|
+
```
|
725
|
+
|
587
726
|
### Sidecar assets (experimental)
|
588
727
|
|
589
728
|
It’s possible to include Javascript and CSS alongside components, sometimes called "sidecar" assets or files.
|
@@ -731,6 +870,8 @@ ViewComponent is far from a novel idea! Popular implementations of view componen
|
|
731
870
|
## Resources
|
732
871
|
|
733
872
|
- [Encapsulating Views, RailsConf 2020](https://youtu.be/YVYRus_2KZM)
|
873
|
+
- [Rethinking the View Layer with Components, Ruby Rogues Podcast](https://devchat.tv/ruby-rogues/rr-461-rethinking-the-view-layer-with-components-with-joel-hawksley/)
|
874
|
+
- [ViewComponents in Action with Andrew Mason, Ruby on Rails Podcast](https://5by5.tv/rubyonrails/320)
|
734
875
|
- [ViewComponent at GitHub with Joel Hawksley](https://the-ruby-blend.fireside.fm/9)
|
735
876
|
- [Components, HAML vs ERB, and Design Systems](https://the-ruby-blend.fireside.fm/4)
|
736
877
|
- [Choosing the Right Tech Stack with Dave Paola](https://5by5.tv/rubyonrails/307)
|
@@ -783,6 +924,16 @@ ViewComponent is built by:
|
|
783
924
|
|@simonrand|@fugufish|@cover|@franks921|@fsateler|
|
784
925
|
|Dublin, Ireland|Salt Lake City, Utah|Barcelona|South Africa|Chile|
|
785
926
|
|
927
|
+
|<img src="https://avatars.githubusercontent.com/maxbeizer?s=256" alt="maxbeizer" width="128" />|<img src="https://avatars.githubusercontent.com/franco?s=256" alt="franco" width="128" />|<img src="https://avatars.githubusercontent.com/tbroad-ramsey?s=256" alt="tbroad-ramsey" width="128" />|<img src="https://avatars.githubusercontent.com/jensljungblad?s=256" alt="jensljungblad" width="128" />|<img src="https://avatars.githubusercontent.com/bbugh?s=256" alt="bbugh" width="128" />|
|
928
|
+
|:---:|:---:|:---:|:---:|:---:|
|
929
|
+
|@maxbeizer|@franco|@tbroad-ramsey|@jensljungblad|@bbugh|
|
930
|
+
|Nashville, TN|Switzerland|Spring Hill, TN|New York, NY|Austin, TX|
|
931
|
+
|
932
|
+
|<img src="https://avatars.githubusercontent.com/johannesengl?s=256" alt="johannesengl" width="128" />|
|
933
|
+
|:---:|
|
934
|
+
|@johannesengl|
|
935
|
+
|Berlin, Germany|
|
936
|
+
|
786
937
|
## License
|
787
938
|
|
788
939
|
ViewComponent is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/view_component/base.rb
CHANGED
@@ -5,6 +5,7 @@ require "active_support/configurable"
|
|
5
5
|
require "view_component/collection"
|
6
6
|
require "view_component/compile_cache"
|
7
7
|
require "view_component/previewable"
|
8
|
+
require "view_component/slotable"
|
8
9
|
|
9
10
|
module ViewComponent
|
10
11
|
class Base < ActionView::Base
|
@@ -12,11 +13,15 @@ module ViewComponent
|
|
12
13
|
include ViewComponent::Previewable
|
13
14
|
|
14
15
|
# For CSRF authenticity tokens in forms
|
15
|
-
delegate :form_authenticity_token, :protect_against_forgery?, to: :helpers
|
16
|
+
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
16
17
|
|
17
18
|
class_attribute :content_areas
|
18
19
|
self.content_areas = [] # class_attribute:default doesn't work until Rails 5.2
|
19
20
|
|
21
|
+
# Hash of registered Slots
|
22
|
+
class_attribute :slots
|
23
|
+
self.slots = {}
|
24
|
+
|
20
25
|
# Entrypoint for rendering components.
|
21
26
|
#
|
22
27
|
# view_context: ActionView context from calling view
|
@@ -106,9 +111,9 @@ module ViewComponent
|
|
106
111
|
@controller ||= view_context.controller
|
107
112
|
end
|
108
113
|
|
109
|
-
# Provides a proxy to access helper methods
|
114
|
+
# Provides a proxy to access helper methods from the context of the current controller
|
110
115
|
def helpers
|
111
|
-
@helpers ||= view_context
|
116
|
+
@helpers ||= controller.view_context
|
112
117
|
end
|
113
118
|
|
114
119
|
# Removes the first part of the path and the extension.
|
@@ -157,12 +162,15 @@ module ViewComponent
|
|
157
162
|
mattr_accessor :test_controller
|
158
163
|
@@test_controller = "ApplicationController"
|
159
164
|
|
165
|
+
# Configure if render monkey patches should be included or not in Rails <6.1.
|
166
|
+
mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
|
167
|
+
|
160
168
|
class << self
|
161
169
|
attr_accessor :source_location
|
162
170
|
|
163
171
|
# Render a component collection.
|
164
|
-
def with_collection(
|
165
|
-
Collection.new(self,
|
172
|
+
def with_collection(collection, **args)
|
173
|
+
Collection.new(self, collection, **args)
|
166
174
|
end
|
167
175
|
|
168
176
|
# Provide identifier for ActionView template annotations
|
@@ -181,6 +189,10 @@ module ViewComponent
|
|
181
189
|
# has been re-defined by the consuming application, likely in ApplicationComponent.
|
182
190
|
child.source_location = caller_locations(1, 10).reject { |l| l.label == "inherited" }[0].absolute_path
|
183
191
|
|
192
|
+
# Clone slot configuration into child class
|
193
|
+
# see #test_slots_pollution
|
194
|
+
child.slots = self.slots.clone
|
195
|
+
|
184
196
|
super
|
185
197
|
end
|
186
198
|
|
@@ -307,7 +319,16 @@ module ViewComponent
|
|
307
319
|
parameter = validate_default ? collection_parameter : provided_collection_parameter
|
308
320
|
|
309
321
|
return unless parameter
|
310
|
-
return if
|
322
|
+
return if initialize_parameters.map(&:last).include?(parameter)
|
323
|
+
|
324
|
+
# If Ruby cannot parse the component class, then the initalize
|
325
|
+
# parameters will be empty and ViewComponent will not be able to render
|
326
|
+
# the component.
|
327
|
+
if initialize_parameters.empty?
|
328
|
+
raise ArgumentError.new(
|
329
|
+
"#{self} initializer is empty or invalid."
|
330
|
+
)
|
331
|
+
end
|
311
332
|
|
312
333
|
raise ArgumentError.new(
|
313
334
|
"#{self} initializer must accept " \
|
@@ -317,6 +338,10 @@ module ViewComponent
|
|
317
338
|
|
318
339
|
private
|
319
340
|
|
341
|
+
def initialize_parameters
|
342
|
+
instance_method(:initialize).parameters
|
343
|
+
end
|
344
|
+
|
320
345
|
def provided_collection_parameter
|
321
346
|
@provided_collection_parameter ||= nil
|
322
347
|
end
|
@@ -9,7 +9,7 @@ module ViewComponent
|
|
9
9
|
@component.validate_collection_parameter!(validate_default: true)
|
10
10
|
|
11
11
|
@collection.map do |item|
|
12
|
-
content = @component.new(component_options(item, iterator)).render_in(view_context, &block)
|
12
|
+
content = @component.new(**component_options(item, iterator)).render_in(view_context, &block)
|
13
13
|
iterator.iterate!
|
14
14
|
content
|
15
15
|
end.join.html_safe
|
@@ -10,6 +10,7 @@ module ViewComponent
|
|
10
10
|
initializer "view_component.set_configs" do |app|
|
11
11
|
options = app.config.view_component
|
12
12
|
|
13
|
+
options.render_monkey_patch_enabled = true if options.render_monkey_patch_enabled.nil?
|
13
14
|
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
14
15
|
options.preview_route ||= ViewComponent::Base.preview_route
|
15
16
|
|
@@ -42,21 +43,35 @@ module ViewComponent
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
|
-
initializer "view_component.monkey_patch_render" do
|
46
|
+
initializer "view_component.monkey_patch_render" do |app|
|
47
|
+
next if Rails.version.to_f >= 6.1 || !app.config.view_component.render_monkey_patch_enabled
|
48
|
+
|
46
49
|
ActiveSupport.on_load(:action_view) do
|
47
|
-
|
48
|
-
|
49
|
-
ActionView::Base.prepend ViewComponent::RenderMonkeyPatch
|
50
|
-
end
|
50
|
+
require "view_component/render_monkey_patch"
|
51
|
+
ActionView::Base.prepend ViewComponent::RenderMonkeyPatch
|
51
52
|
end
|
52
53
|
|
53
54
|
ActiveSupport.on_load(:action_controller) do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
require "view_component/rendering_monkey_patch"
|
56
|
+
require "view_component/render_to_string_monkey_patch"
|
57
|
+
ActionController::Base.prepend ViewComponent::RenderingMonkeyPatch
|
58
|
+
ActionController::Base.prepend ViewComponent::RenderToStringMonkeyPatch
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
initializer "view_component.include_render_component" do |app|
|
63
|
+
next if Rails.version.to_f >= 6.1
|
64
|
+
|
65
|
+
ActiveSupport.on_load(:action_view) do
|
66
|
+
require "view_component/render_component_helper"
|
67
|
+
ActionView::Base.include ViewComponent::RenderComponentHelper
|
68
|
+
end
|
69
|
+
|
70
|
+
ActiveSupport.on_load(:action_controller) do
|
71
|
+
require "view_component/rendering_component_helper"
|
72
|
+
require "view_component/render_component_to_string_helper"
|
73
|
+
ActionController::Base.include ViewComponent::RenderingComponentHelper
|
74
|
+
ActionController::Base.include ViewComponent::RenderComponentToStringHelper
|
60
75
|
end
|
61
76
|
end
|
62
77
|
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
require "view_component/slot"
|
6
|
+
|
7
|
+
module ViewComponent
|
8
|
+
module Slotable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
# support initializing slots as:
|
13
|
+
#
|
14
|
+
# with_slot(
|
15
|
+
# :header,
|
16
|
+
# collection: true|false,
|
17
|
+
# class_name: "Header" # class name string, used to instantiate Slot
|
18
|
+
# )
|
19
|
+
def with_slot(*slot_names, collection: false, class_name: nil)
|
20
|
+
slot_names.each do |slot_name|
|
21
|
+
# Ensure slot_name is not already declared
|
22
|
+
if self.slots.key?(slot_name)
|
23
|
+
raise ArgumentError.new("#{slot_name} slot declared multiple times")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Ensure slot name is not :content
|
27
|
+
if slot_name == :content
|
28
|
+
raise ArgumentError.new ":content is a reserved slot name. Please use another name, such as ':body'"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set the name of the method used to access the Slot(s)
|
32
|
+
accessor_name =
|
33
|
+
if collection
|
34
|
+
# If Slot is a collection, set the accessor
|
35
|
+
# name to the pluralized form of the slot name
|
36
|
+
# For example: :tab => :tabs
|
37
|
+
ActiveSupport::Inflector.pluralize(slot_name)
|
38
|
+
else
|
39
|
+
slot_name
|
40
|
+
end
|
41
|
+
|
42
|
+
instance_variable_name = "@#{accessor_name}"
|
43
|
+
|
44
|
+
# If the slot is a collection, define an accesor that defaults to an empty array
|
45
|
+
if collection
|
46
|
+
class_eval <<-RUBY
|
47
|
+
def #{accessor_name}
|
48
|
+
#{instance_variable_name} ||= []
|
49
|
+
end
|
50
|
+
RUBY
|
51
|
+
else
|
52
|
+
attr_reader accessor_name
|
53
|
+
end
|
54
|
+
|
55
|
+
# Default class_name to ViewComponent::Slot
|
56
|
+
class_name = "ViewComponent::Slot" unless class_name.present?
|
57
|
+
|
58
|
+
# Register the slot on the component
|
59
|
+
self.slots[slot_name] = {
|
60
|
+
class_name: class_name,
|
61
|
+
instance_variable_name: instance_variable_name,
|
62
|
+
collection: collection
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Build a Slot instance on a component,
|
69
|
+
# exposing it for use inside the
|
70
|
+
# component template.
|
71
|
+
#
|
72
|
+
# slot: Name of Slot, in symbol form
|
73
|
+
# **args: Arguments to be passed to Slot initializer
|
74
|
+
#
|
75
|
+
# For example:
|
76
|
+
# <%= render(SlotsComponent.new) do |component| %>
|
77
|
+
# <% component.slot(:footer, class_names: "footer-class") do %>
|
78
|
+
# <p>This is my footer!</p>
|
79
|
+
# <% end %>
|
80
|
+
# <% end %>
|
81
|
+
#
|
82
|
+
def slot(slot_name, **args, &block)
|
83
|
+
# Raise ArgumentError if `slot` does not exist
|
84
|
+
unless slots.keys.include?(slot_name)
|
85
|
+
raise ArgumentError.new "Unknown slot '#{slot_name}' - expected one of '#{slots.keys}'"
|
86
|
+
end
|
87
|
+
|
88
|
+
slot = slots[slot_name]
|
89
|
+
|
90
|
+
# The class name of the Slot, such as Header
|
91
|
+
slot_class = self.class.const_get(slot[:class_name])
|
92
|
+
|
93
|
+
unless slot_class <= ViewComponent::Slot
|
94
|
+
raise ArgumentError.new "#{slot[:class_name]} must inherit from ViewComponent::Slot"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Instantiate Slot class, accommodating Slots that don't accept arguments
|
98
|
+
slot_instance = args.present? ? slot_class.new(args) : slot_class.new
|
99
|
+
|
100
|
+
# Capture block and assign to slot_instance#content
|
101
|
+
slot_instance.content = view_context.capture(&block) if block_given?
|
102
|
+
|
103
|
+
if slot[:collection]
|
104
|
+
# Initialize instance variable as an empty array
|
105
|
+
# if slot is a collection and has yet to be initialized
|
106
|
+
unless instance_variable_defined?(slot[:instance_variable_name])
|
107
|
+
instance_variable_set(slot[:instance_variable_name], [])
|
108
|
+
end
|
109
|
+
|
110
|
+
# Append Slot instance to collection accessor Array
|
111
|
+
instance_variable_get(slot[:instance_variable_name]) << slot_instance
|
112
|
+
else
|
113
|
+
# Assign the Slot instance to the slot accessor
|
114
|
+
instance_variable_set(slot[:instance_variable_name], slot_instance)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Return nil, as this method should not output anything to the view itself.
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -204,9 +204,14 @@ files:
|
|
204
204
|
- lib/view_component/engine.rb
|
205
205
|
- lib/view_component/preview.rb
|
206
206
|
- lib/view_component/previewable.rb
|
207
|
+
- lib/view_component/render_component_helper.rb
|
208
|
+
- lib/view_component/render_component_to_string_helper.rb
|
207
209
|
- lib/view_component/render_monkey_patch.rb
|
208
210
|
- lib/view_component/render_to_string_monkey_patch.rb
|
211
|
+
- lib/view_component/rendering_component_helper.rb
|
209
212
|
- lib/view_component/rendering_monkey_patch.rb
|
213
|
+
- lib/view_component/slot.rb
|
214
|
+
- lib/view_component/slotable.rb
|
210
215
|
- lib/view_component/template_error.rb
|
211
216
|
- lib/view_component/test_case.rb
|
212
217
|
- lib/view_component/test_helpers.rb
|