view_component 4.0.0.alpha5 → 4.0.0.alpha7
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 +9 -5
- data/app/controllers/view_components_system_test_controller.rb +1 -3
- data/app/views/test_mailer/test_url_email.html.erb +1 -0
- data/docs/CHANGELOG.md +86 -4
- data/lib/view_component/base.rb +91 -143
- data/lib/view_component/compiler.rb +14 -7
- data/lib/view_component/config.rb +41 -46
- data/lib/view_component/configurable.rb +1 -1
- data/lib/view_component/engine.rb +10 -10
- data/lib/view_component/errors.rb +0 -12
- data/lib/view_component/inline_template.rb +4 -4
- data/lib/view_component/preview.rb +1 -1
- data/lib/view_component/slot.rb +10 -15
- data/lib/view_component/slotable.rb +49 -45
- data/lib/view_component/template.rb +3 -3
- data/lib/view_component/test_helpers.rb +15 -2
- data/lib/view_component/translatable.rb +7 -7
- data/lib/view_component/version.rb +1 -1
- data/lib/view_component.rb +7 -5
- metadata +2 -410
- data/lib/view_component/component_local_config.rb +0 -60
- data/lib/view_component/slotable_default.rb +0 -18
- data/lib/view_component/use_helpers.rb +0 -41
@@ -13,14 +13,8 @@ module ViewComponent
|
|
13
13
|
def defaults
|
14
14
|
ActiveSupport::OrderedOptions.new.merge!({
|
15
15
|
generate: default_generate_options,
|
16
|
-
|
17
|
-
|
18
|
-
instrumentation_enabled: false,
|
19
|
-
component_parent_class: nil,
|
20
|
-
show_previews: Rails.env.development? || Rails.env.test?,
|
21
|
-
preview_paths: default_preview_paths,
|
22
|
-
test_controller: "ApplicationController",
|
23
|
-
default_preview_layout: nil
|
16
|
+
previews: default_previews_options,
|
17
|
+
instrumentation_enabled: false
|
24
18
|
})
|
25
19
|
end
|
26
20
|
|
@@ -84,7 +78,7 @@ module ViewComponent
|
|
84
78
|
#
|
85
79
|
# Required when there is more than one path defined in preview_paths.
|
86
80
|
# Defaults to `""`. If this is blank, the generator will use
|
87
|
-
# `ViewComponent.config.
|
81
|
+
# `ViewComponent.config.previews.paths` if defined,
|
88
82
|
# `"test/components/previews"` otherwise
|
89
83
|
#
|
90
84
|
# #### `#use_component_path_for_rspec_tests`
|
@@ -100,49 +94,40 @@ module ViewComponent
|
|
100
94
|
# `app/views/components`, then the generator will create a new spec file
|
101
95
|
# in `spec/views/components/` rather than the default `spec/components/`.
|
102
96
|
|
103
|
-
# @!attribute
|
104
|
-
# @return [
|
105
|
-
# The
|
106
|
-
#
|
107
|
-
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
97
|
+
# @!attribute previews
|
98
|
+
# @return [ActiveSupport::OrderedOptions]
|
99
|
+
# The subset of configuration options relating to previews.
|
100
|
+
#
|
101
|
+
# #### `#controller`
|
102
|
+
#
|
103
|
+
# The controller used for previewing components. Defaults to `ViewComponentsController`:
|
104
|
+
#
|
105
|
+
# config.view_component.previews.controller = "MyPreviewController"
|
106
|
+
#
|
107
|
+
# #### `#route`
|
108
|
+
#
|
109
|
+
# The entry route for component previews. Defaults to `/rails/view_components`:
|
110
|
+
#
|
111
|
+
# config.view_component.previews.route = "/my_previews"
|
112
|
+
#
|
113
|
+
# #### `#enabled`
|
114
|
+
#
|
115
|
+
# Whether component previews are enabled. Defaults to `true` in development and test environments:
|
116
|
+
#
|
117
|
+
# config.view_component.previews.enabled = false
|
118
|
+
#
|
119
|
+
# #### `#default_layout`
|
120
|
+
#
|
121
|
+
# A custom default layout used for the previews index page and individual previews. Defaults to `nil`:
|
122
|
+
#
|
123
|
+
# config.view_component.previews.default_layout = "preview_layout"
|
124
|
+
#
|
112
125
|
|
113
126
|
# @!attribute instrumentation_enabled
|
114
127
|
# @return [Boolean]
|
115
128
|
# Whether ActiveSupport notifications are enabled.
|
116
129
|
# Defaults to `false`.
|
117
130
|
|
118
|
-
# @!attribute component_parent_class
|
119
|
-
# @return [String]
|
120
|
-
# The parent class from which generated components will inherit.
|
121
|
-
# Defaults to `nil`. If this is falsy, generators will use
|
122
|
-
# `"ApplicationComponent"` if defined, `"ViewComponent::Base"` otherwise.
|
123
|
-
|
124
|
-
# @!attribute show_previews
|
125
|
-
# @return [Boolean]
|
126
|
-
# Whether component previews are enabled.
|
127
|
-
# Defaults to `true` in development and test environments.
|
128
|
-
|
129
|
-
# @!attribute preview_paths
|
130
|
-
# @return [Array<String>]
|
131
|
-
# The locations in which component previews will be looked up.
|
132
|
-
# Defaults to `['test/components/previews']` relative to your Rails root.
|
133
|
-
|
134
|
-
# @!attribute test_controller
|
135
|
-
# @return [String]
|
136
|
-
# The controller used for testing components.
|
137
|
-
# Can also be configured on a per-test basis using `#with_controller_class`.
|
138
|
-
# Defaults to `ApplicationController`.
|
139
|
-
|
140
|
-
# @!attribute default_preview_layout
|
141
|
-
# @return [String]
|
142
|
-
# A custom default layout used for the previews index page and individual
|
143
|
-
# previews.
|
144
|
-
# Defaults to `nil`. If this is falsy, `"component_preview"` is used.
|
145
|
-
|
146
131
|
def default_preview_paths
|
147
132
|
(default_rails_preview_paths + default_rails_engines_preview_paths).uniq
|
148
133
|
end
|
@@ -173,6 +158,16 @@ module ViewComponent
|
|
173
158
|
options.path = "app/components"
|
174
159
|
options
|
175
160
|
end
|
161
|
+
|
162
|
+
def default_previews_options
|
163
|
+
options = ActiveSupport::OrderedOptions.new
|
164
|
+
options.controller = "ViewComponentsController"
|
165
|
+
options.route = "/rails/view_components"
|
166
|
+
options.enabled = Rails.env.development? || Rails.env.test?
|
167
|
+
options.default_layout = nil
|
168
|
+
options.paths = default_preview_paths
|
169
|
+
options
|
170
|
+
end
|
176
171
|
end
|
177
172
|
|
178
173
|
# @!attribute current
|
@@ -5,7 +5,7 @@ module ViewComponent
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
next if respond_to?(:config) && config.respond_to?(:view_component) && config.respond_to_missing?(:
|
8
|
+
next if respond_to?(:config) && config.respond_to?(:view_component) && config.respond_to_missing?(:instrumentation_enabled)
|
9
9
|
|
10
10
|
include ActiveSupport::Configurable
|
11
11
|
|
@@ -11,15 +11,15 @@ module ViewComponent
|
|
11
11
|
initializer "view_component.set_configs" do |app|
|
12
12
|
options = app.config.view_component
|
13
13
|
|
14
|
-
%i[generate
|
14
|
+
%i[generate previews].each do |config_option|
|
15
15
|
options[config_option] ||= ViewComponent::Base.public_send(config_option)
|
16
16
|
end
|
17
17
|
options.instrumentation_enabled = false if options.instrumentation_enabled.nil?
|
18
|
-
options.
|
18
|
+
options.previews.enabled = (Rails.env.development? || Rails.env.test?) if options.previews.enabled.nil?
|
19
19
|
|
20
|
-
if options.
|
20
|
+
if options.previews.enabled
|
21
21
|
# This is still necessary because when `config.view_component` is declared, `Rails.root` is unspecified.
|
22
|
-
options.
|
22
|
+
options.previews.paths << "#{Rails.root}/test/components/previews" if defined?(Rails.root) && Dir.exist?(
|
23
23
|
"#{Rails.root}/test/components/previews"
|
24
24
|
)
|
25
25
|
end
|
@@ -36,8 +36,8 @@ module ViewComponent
|
|
36
36
|
initializer "view_component.set_autoload_paths" do |app|
|
37
37
|
options = app.config.view_component
|
38
38
|
|
39
|
-
if options.
|
40
|
-
paths_to_add = options.
|
39
|
+
if options.previews.enabled && !options.previews.paths.empty?
|
40
|
+
paths_to_add = options.previews.paths - ActiveSupport::Dependencies.autoload_paths
|
41
41
|
ActiveSupport::Dependencies.autoload_paths.concat(paths_to_add) if paths_to_add.any?
|
42
42
|
end
|
43
43
|
end
|
@@ -88,19 +88,19 @@ module ViewComponent
|
|
88
88
|
config.after_initialize do |app|
|
89
89
|
options = app.config.view_component
|
90
90
|
|
91
|
-
if options.
|
91
|
+
if options.previews.enabled
|
92
92
|
app.routes.prepend do
|
93
|
-
preview_controller = options.
|
93
|
+
preview_controller = options.previews.controller.sub(/Controller$/, "").underscore
|
94
94
|
|
95
95
|
get(
|
96
|
-
options.
|
96
|
+
options.previews.route,
|
97
97
|
to: "#{preview_controller}#index",
|
98
98
|
as: :preview_view_components,
|
99
99
|
internal: true
|
100
100
|
)
|
101
101
|
|
102
102
|
get(
|
103
|
-
"#{options.
|
103
|
+
"#{options.previews.route}/*path",
|
104
104
|
to: "#{preview_controller}#previews",
|
105
105
|
as: :preview_view_component,
|
106
106
|
internal: true
|
@@ -65,18 +65,6 @@ module ViewComponent
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
class EmptyOrInvalidInitializerError < StandardError
|
69
|
-
MESSAGE =
|
70
|
-
"The COMPONENT initializer is empty or invalid. " \
|
71
|
-
"It must accept the parameter `PARAMETER` to render it as a collection.\n\n" \
|
72
|
-
"To fix this issue, update the initializer to accept `PARAMETER`.\n\n" \
|
73
|
-
"See [the collections docs](https://viewcomponent.org/guide/collections.html) for more information on rendering collections."
|
74
|
-
|
75
|
-
def initialize(klass_name, parameter)
|
76
|
-
super(MESSAGE.gsub("COMPONENT", klass_name.to_s).gsub("PARAMETER", parameter.to_s))
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
68
|
class MissingCollectionArgumentError < StandardError
|
81
69
|
MESSAGE =
|
82
70
|
"The initializer for COMPONENT doesn't accept the parameter `PARAMETER`, " \
|
@@ -9,7 +9,7 @@ module ViewComponent # :nodoc:
|
|
9
9
|
def method_missing(method, *args)
|
10
10
|
return super if !method.end_with?("_template")
|
11
11
|
|
12
|
-
if @__vc_inline_template_defined
|
12
|
+
if defined?(@__vc_inline_template_defined) && @__vc_inline_template_defined
|
13
13
|
raise MultipleInlineTemplatesError
|
14
14
|
end
|
15
15
|
|
@@ -37,12 +37,12 @@ module ViewComponent # :nodoc:
|
|
37
37
|
method.end_with?("_template") || super
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
@__vc_inline_template
|
40
|
+
def __vc_inline_template
|
41
|
+
@__vc_inline_template if defined?(@__vc_inline_template)
|
42
42
|
end
|
43
43
|
|
44
44
|
def __vc_inline_template_language
|
45
|
-
@__vc_inline_template_language
|
45
|
+
@__vc_inline_template_language if defined?(@__vc_inline_template_language)
|
46
46
|
end
|
47
47
|
|
48
48
|
def inherited(subclass)
|
data/lib/view_component/slot.rb
CHANGED
@@ -9,18 +9,13 @@ module ViewComponent
|
|
9
9
|
attr_writer :__vc_component_instance, :__vc_content_block, :__vc_content
|
10
10
|
|
11
11
|
def initialize(parent)
|
12
|
-
@content = nil
|
13
|
-
@__vc_component_instance = nil
|
14
|
-
@__vc_content = nil
|
15
|
-
@__vc_content_block = nil
|
16
|
-
@__vc_content_set_by_with_content = nil
|
17
12
|
@parent = parent
|
18
13
|
end
|
19
14
|
|
20
15
|
def content?
|
21
|
-
return true if @__vc_content.present?
|
22
|
-
return true if @__vc_content_set_by_with_content.present?
|
23
|
-
return true if @__vc_content_block.present?
|
16
|
+
return true if defined?(@__vc_content) && @__vc_content.present?
|
17
|
+
return true if defined?(@__vc_content_set_by_with_content) && @__vc_content_set_by_with_content.present?
|
18
|
+
return true if defined?(@__vc_content_block) && @__vc_content_block.present?
|
24
19
|
return false if !__vc_component_instance?
|
25
20
|
|
26
21
|
@__vc_component_instance.content?
|
@@ -48,11 +43,11 @@ module ViewComponent
|
|
48
43
|
# If there is no slot renderable, we evaluate the block passed to
|
49
44
|
# the slot and return it.
|
50
45
|
def to_s
|
51
|
-
return @content if
|
46
|
+
return @content if defined?(@content)
|
52
47
|
|
53
48
|
view_context = @parent.send(:view_context)
|
54
49
|
|
55
|
-
if
|
50
|
+
if defined?(@__vc_content_block) && defined?(@__vc_content_set_by_with_content)
|
56
51
|
raise DuplicateSlotContentError.new(self.class.name)
|
57
52
|
end
|
58
53
|
|
@@ -60,7 +55,7 @@ module ViewComponent
|
|
60
55
|
if __vc_component_instance?
|
61
56
|
@__vc_component_instance.__vc_original_view_context = @parent.__vc_original_view_context
|
62
57
|
|
63
|
-
if
|
58
|
+
if defined?(@__vc_content_block)
|
64
59
|
# render_in is faster than `parent.render`
|
65
60
|
@__vc_component_instance.render_in(view_context) do |*args|
|
66
61
|
@__vc_content_block.call(*args)
|
@@ -68,11 +63,11 @@ module ViewComponent
|
|
68
63
|
else
|
69
64
|
@__vc_component_instance.render_in(view_context)
|
70
65
|
end
|
71
|
-
elsif
|
66
|
+
elsif defined?(@__vc_content)
|
72
67
|
@__vc_content
|
73
|
-
elsif
|
68
|
+
elsif defined?(@__vc_content_block)
|
74
69
|
view_context.capture(&@__vc_content_block)
|
75
|
-
elsif
|
70
|
+
elsif defined?(@__vc_content_set_by_with_content)
|
76
71
|
@__vc_content_set_by_with_content
|
77
72
|
end
|
78
73
|
|
@@ -113,7 +108,7 @@ module ViewComponent
|
|
113
108
|
private
|
114
109
|
|
115
110
|
def __vc_component_instance?
|
116
|
-
|
111
|
+
defined?(@__vc_component_instance)
|
117
112
|
end
|
118
113
|
end
|
119
114
|
end
|
@@ -73,25 +73,25 @@ module ViewComponent
|
|
73
73
|
#
|
74
74
|
# <%= render_inline(MyComponent.new.with_header_content("Foo")) %>
|
75
75
|
def renders_one(slot_name, callable = nil)
|
76
|
-
|
76
|
+
__vc_validate_singular_slot_name(slot_name)
|
77
77
|
|
78
78
|
if callable.is_a?(Hash) && callable.key?(:types)
|
79
|
-
|
79
|
+
__vc_register_polymorphic_slot(slot_name, callable[:types], collection: false)
|
80
80
|
else
|
81
|
-
|
81
|
+
__vc_validate_plural_slot_name(ActiveSupport::Inflector.pluralize(slot_name).to_sym)
|
82
82
|
|
83
83
|
setter_method_name = :"with_#{slot_name}"
|
84
84
|
|
85
85
|
define_method setter_method_name do |*args, **kwargs, &block|
|
86
|
-
|
86
|
+
__vc_set_slot(slot_name, nil, *args, **kwargs, &block)
|
87
87
|
end
|
88
88
|
|
89
89
|
self::GeneratedSlotMethods.define_method slot_name do
|
90
|
-
|
90
|
+
__vc_get_slot(slot_name)
|
91
91
|
end
|
92
92
|
|
93
93
|
self::GeneratedSlotMethods.define_method :"#{slot_name}?" do
|
94
|
-
|
94
|
+
__vc_get_slot(slot_name).present?
|
95
95
|
end
|
96
96
|
|
97
97
|
define_method :"with_#{slot_name}_content" do |content|
|
@@ -100,7 +100,7 @@ module ViewComponent
|
|
100
100
|
self
|
101
101
|
end
|
102
102
|
|
103
|
-
|
103
|
+
__vc_register_slot(slot_name, collection: false, callable: callable)
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -142,18 +142,18 @@ module ViewComponent
|
|
142
142
|
# <% end %>
|
143
143
|
# <% end %>
|
144
144
|
def renders_many(slot_name, callable = nil)
|
145
|
-
|
145
|
+
__vc_validate_plural_slot_name(slot_name)
|
146
146
|
|
147
147
|
if callable.is_a?(Hash) && callable.key?(:types)
|
148
|
-
|
148
|
+
__vc_register_polymorphic_slot(slot_name, callable[:types], collection: true)
|
149
149
|
else
|
150
150
|
singular_name = ActiveSupport::Inflector.singularize(slot_name)
|
151
|
-
|
151
|
+
__vc_validate_singular_slot_name(ActiveSupport::Inflector.singularize(slot_name).to_sym)
|
152
152
|
|
153
153
|
setter_method_name = :"with_#{singular_name}"
|
154
154
|
|
155
155
|
define_method setter_method_name do |*args, **kwargs, &block|
|
156
|
-
|
156
|
+
__vc_set_slot(slot_name, nil, *args, **kwargs, &block)
|
157
157
|
end
|
158
158
|
|
159
159
|
define_method :"with_#{singular_name}_content" do |content|
|
@@ -165,22 +165,22 @@ module ViewComponent
|
|
165
165
|
define_method :"with_#{slot_name}" do |collection_args = nil, &block|
|
166
166
|
collection_args.map do |args|
|
167
167
|
if args.respond_to?(:to_hash)
|
168
|
-
|
168
|
+
__vc_set_slot(slot_name, nil, **args, &block)
|
169
169
|
else
|
170
|
-
|
170
|
+
__vc_set_slot(slot_name, nil, *args, &block)
|
171
171
|
end
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
175
175
|
self::GeneratedSlotMethods.define_method slot_name do
|
176
|
-
|
176
|
+
__vc_get_slot(slot_name)
|
177
177
|
end
|
178
178
|
|
179
179
|
self::GeneratedSlotMethods.define_method :"#{slot_name}?" do
|
180
|
-
|
180
|
+
__vc_get_slot(slot_name).present?
|
181
181
|
end
|
182
182
|
|
183
|
-
|
183
|
+
__vc_register_slot(slot_name, collection: true, callable: callable)
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
@@ -211,10 +211,12 @@ module ViewComponent
|
|
211
211
|
super
|
212
212
|
end
|
213
213
|
|
214
|
+
# @private
|
214
215
|
# Called by the compiler, as instance methods are not defined when slots are first registered
|
215
|
-
def
|
216
|
+
def __vc_register_default_slots
|
216
217
|
registered_slots.each do |slot_name, config|
|
217
|
-
|
218
|
+
default_method_name = :"default_#{slot_name}"
|
219
|
+
config[:default_method] = instance_methods.find { |method_name| method_name == default_method_name }
|
218
220
|
|
219
221
|
registered_slots[slot_name] = config
|
220
222
|
end
|
@@ -222,17 +224,17 @@ module ViewComponent
|
|
222
224
|
|
223
225
|
private
|
224
226
|
|
225
|
-
def
|
226
|
-
registered_slots[slot_name] =
|
227
|
+
def __vc_register_slot(slot_name, **kwargs)
|
228
|
+
registered_slots[slot_name] = __vc_define_slot(slot_name, **kwargs)
|
227
229
|
end
|
228
230
|
|
229
|
-
def
|
231
|
+
def __vc_register_polymorphic_slot(slot_name, types, collection:)
|
230
232
|
self::GeneratedSlotMethods.define_method(slot_name) do
|
231
|
-
|
233
|
+
__vc_get_slot(slot_name)
|
232
234
|
end
|
233
235
|
|
234
236
|
self::GeneratedSlotMethods.define_method(:"#{slot_name}?") do
|
235
|
-
|
237
|
+
__vc_get_slot(slot_name).present?
|
236
238
|
end
|
237
239
|
|
238
240
|
renderable_hash = types.each_with_object({}) do |(poly_type, poly_attributes_or_callable), memo|
|
@@ -251,7 +253,7 @@ module ViewComponent
|
|
251
253
|
"#{slot_name}_#{poly_type}"
|
252
254
|
end
|
253
255
|
|
254
|
-
memo[poly_type] =
|
256
|
+
memo[poly_type] = __vc_define_slot(
|
255
257
|
poly_slot_name, collection: collection, callable: poly_callable
|
256
258
|
)
|
257
259
|
|
@@ -262,7 +264,7 @@ module ViewComponent
|
|
262
264
|
end
|
263
265
|
|
264
266
|
define_method(setter_method_name) do |*args, **kwargs, &block|
|
265
|
-
|
267
|
+
__vc_set_polymorphic_slot(slot_name, poly_type, *args, **kwargs, &block)
|
266
268
|
end
|
267
269
|
|
268
270
|
define_method :"with_#{poly_slot_name}_content" do |content|
|
@@ -278,7 +280,7 @@ module ViewComponent
|
|
278
280
|
}
|
279
281
|
end
|
280
282
|
|
281
|
-
def
|
283
|
+
def __vc_define_slot(slot_name, collection:, callable:)
|
282
284
|
slot = {collection: collection}
|
283
285
|
return slot unless callable
|
284
286
|
|
@@ -301,18 +303,18 @@ module ViewComponent
|
|
301
303
|
slot
|
302
304
|
end
|
303
305
|
|
304
|
-
def
|
306
|
+
def __vc_validate_plural_slot_name(slot_name)
|
305
307
|
if RESERVED_NAMES[:plural].include?(slot_name.to_sym)
|
306
308
|
raise ReservedPluralSlotNameError.new(name, slot_name)
|
307
309
|
end
|
308
310
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
311
|
+
__vc_raise_if_slot_name_uncountable(slot_name)
|
312
|
+
__vc_raise_if_slot_conflicts_with_call(slot_name)
|
313
|
+
__vc_raise_if_slot_ends_with_question_mark(slot_name)
|
314
|
+
__vc_raise_if_slot_registered(slot_name)
|
313
315
|
end
|
314
316
|
|
315
|
-
def
|
317
|
+
def __vc_validate_singular_slot_name(slot_name)
|
316
318
|
if slot_name.to_sym == :content
|
317
319
|
raise ContentSlotNameError.new(name)
|
318
320
|
end
|
@@ -321,28 +323,28 @@ module ViewComponent
|
|
321
323
|
raise ReservedSingularSlotNameError.new(name, slot_name)
|
322
324
|
end
|
323
325
|
|
324
|
-
|
325
|
-
|
326
|
-
|
326
|
+
__vc_raise_if_slot_conflicts_with_call(slot_name)
|
327
|
+
__vc_raise_if_slot_ends_with_question_mark(slot_name)
|
328
|
+
__vc_raise_if_slot_registered(slot_name)
|
327
329
|
end
|
328
330
|
|
329
|
-
def
|
331
|
+
def __vc_raise_if_slot_registered(slot_name)
|
330
332
|
if registered_slots.key?(slot_name)
|
331
333
|
raise RedefinedSlotError.new(name, slot_name)
|
332
334
|
end
|
333
335
|
end
|
334
336
|
|
335
|
-
def
|
337
|
+
def __vc_raise_if_slot_ends_with_question_mark(slot_name)
|
336
338
|
raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.end_with?("?")
|
337
339
|
end
|
338
340
|
|
339
|
-
def
|
341
|
+
def __vc_raise_if_slot_conflicts_with_call(slot_name)
|
340
342
|
if slot_name.start_with?("call_")
|
341
343
|
raise InvalidSlotNameError, "Slot cannot start with 'call_'. Please rename #{slot_name}"
|
342
344
|
end
|
343
345
|
end
|
344
346
|
|
345
|
-
def
|
347
|
+
def __vc_raise_if_slot_name_uncountable(slot_name)
|
346
348
|
slot_name = slot_name.to_s
|
347
349
|
if slot_name.pluralize == slot_name.singularize
|
348
350
|
raise UncountableSlotNameError.new(name, slot_name)
|
@@ -350,9 +352,9 @@ module ViewComponent
|
|
350
352
|
end
|
351
353
|
end
|
352
354
|
|
353
|
-
def
|
355
|
+
def __vc_get_slot(slot_name)
|
354
356
|
@__vc_set_slots ||= {}
|
355
|
-
content unless
|
357
|
+
content unless defined?(@__vc_content_evaluated) && @__vc_content_evaluated # ensure content is loaded so slots will be defined
|
356
358
|
|
357
359
|
# If the slot is set, return it
|
358
360
|
return @__vc_set_slots[slot_name] if @__vc_set_slots[slot_name]
|
@@ -375,7 +377,7 @@ module ViewComponent
|
|
375
377
|
end
|
376
378
|
end
|
377
379
|
|
378
|
-
def
|
380
|
+
def __vc_set_slot(slot_name, slot_definition = nil, *args, **kwargs, &block)
|
379
381
|
slot_definition ||= self.class.registered_slots[slot_name]
|
380
382
|
slot = Slot.new(self)
|
381
383
|
|
@@ -420,6 +422,8 @@ module ViewComponent
|
|
420
422
|
end
|
421
423
|
end
|
422
424
|
|
425
|
+
@__vc_set_slots ||= {}
|
426
|
+
|
423
427
|
if slot_definition[:collection]
|
424
428
|
@__vc_set_slots[slot_name] ||= []
|
425
429
|
@__vc_set_slots[slot_name].push(slot)
|
@@ -430,16 +434,16 @@ module ViewComponent
|
|
430
434
|
slot
|
431
435
|
end
|
432
436
|
|
433
|
-
def
|
437
|
+
def __vc_set_polymorphic_slot(slot_name, poly_type = nil, *args, **kwargs, &block)
|
434
438
|
slot_definition = self.class.registered_slots[slot_name]
|
435
439
|
|
436
|
-
if !slot_definition[:collection] && @__vc_set_slots[slot_name]
|
440
|
+
if !slot_definition[:collection] && defined?(@__vc_set_slots) && @__vc_set_slots[slot_name]
|
437
441
|
raise ContentAlreadySetForPolymorphicSlotError.new(slot_name)
|
438
442
|
end
|
439
443
|
|
440
444
|
poly_def = slot_definition[:renderable_hash][poly_type]
|
441
445
|
|
442
|
-
|
446
|
+
__vc_set_slot(slot_name, poly_def, *args, **kwargs, &block)
|
443
447
|
end
|
444
448
|
end
|
445
449
|
end
|
@@ -43,7 +43,7 @@ module ViewComponent
|
|
43
43
|
attr_reader :source
|
44
44
|
|
45
45
|
def initialize(component:, inline_template:)
|
46
|
-
details = ActionView::TemplateDetails.new(nil, inline_template.language.to_sym,
|
46
|
+
details = ActionView::TemplateDetails.new(nil, inline_template.language.to_sym, DEFAULT_FORMAT, nil)
|
47
47
|
|
48
48
|
super(
|
49
49
|
component: component,
|
@@ -63,7 +63,7 @@ module ViewComponent
|
|
63
63
|
class InlineCall < Template
|
64
64
|
def initialize(component:, method_name:, defined_on_self:)
|
65
65
|
variant = method_name.to_s.include?("call_") ? method_name.to_s.sub("call_", "").to_sym : nil
|
66
|
-
details = ActionView::TemplateDetails.new(nil, nil,
|
66
|
+
details = ActionView::TemplateDetails.new(nil, nil, DEFAULT_FORMAT, variant)
|
67
67
|
|
68
68
|
super(component: component, details: details)
|
69
69
|
|
@@ -82,7 +82,7 @@ module ViewComponent
|
|
82
82
|
def safe_method_name_call
|
83
83
|
m = safe_method_name
|
84
84
|
proc do
|
85
|
-
|
85
|
+
__vc_maybe_escape_html(send(m)) do
|
86
86
|
Kernel.warn("WARNING: The #{self.class} component rendered HTML-unsafe output. " \
|
87
87
|
"The output will be automatically escaped, but you may want to investigate.")
|
88
88
|
end
|
@@ -73,7 +73,7 @@ module ViewComponent
|
|
73
73
|
# @param params [Hash] Parameters to be passed to the preview.
|
74
74
|
# @return [Nokogiri::HTML5]
|
75
75
|
def render_preview(name, from: __vc_test_helpers_preview_class, params: {})
|
76
|
-
previews_controller = __vc_test_helpers_build_controller(Rails.application.config.view_component.
|
76
|
+
previews_controller = __vc_test_helpers_build_controller(Rails.application.config.view_component.previews.controller.constantize)
|
77
77
|
|
78
78
|
# From what I can tell, it's not possible to overwrite all request parameters
|
79
79
|
# at once, so we set them individually here.
|
@@ -233,7 +233,20 @@ module ViewComponent
|
|
233
233
|
#
|
234
234
|
# @return [ActionController::Base]
|
235
235
|
def vc_test_controller
|
236
|
-
@vc_test_controller ||= __vc_test_helpers_build_controller(
|
236
|
+
@vc_test_controller ||= __vc_test_helpers_build_controller(vc_test_controller_class)
|
237
|
+
end
|
238
|
+
|
239
|
+
# Set the controller used by `render_inline`:
|
240
|
+
#
|
241
|
+
# ```ruby
|
242
|
+
# def vc_test_controller_class
|
243
|
+
# MyTestController
|
244
|
+
# end
|
245
|
+
# ```
|
246
|
+
def vc_test_controller_class
|
247
|
+
return @__vc_test_controller_class if defined?(@__vc_test_controller_class)
|
248
|
+
|
249
|
+
defined?(ApplicationController) ? ApplicationController : ActionController::Base
|
237
250
|
end
|
238
251
|
|
239
252
|
# Access the request used by `render_inline`:
|