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.
@@ -13,14 +13,8 @@ module ViewComponent
13
13
  def defaults
14
14
  ActiveSupport::OrderedOptions.new.merge!({
15
15
  generate: default_generate_options,
16
- preview_controller: "ViewComponentsController",
17
- preview_route: "/rails/view_components",
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.preview_paths` if defined,
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 preview_controller
104
- # @return [String]
105
- # The controller used for previewing components.
106
- # Defaults to `ViewComponentsController`.
107
-
108
- # @!attribute preview_route
109
- # @return [String]
110
- # The entry route for component previews.
111
- # Defaults to `"/rails/view_components"`.
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?(:test_controller)
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 preview_controller preview_route].each do |config_option|
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.show_previews = (Rails.env.development? || Rails.env.test?) if options.show_previews.nil?
18
+ options.previews.enabled = (Rails.env.development? || Rails.env.test?) if options.previews.enabled.nil?
19
19
 
20
- if options.show_previews
20
+ if options.previews.enabled
21
21
  # This is still necessary because when `config.view_component` is declared, `Rails.root` is unspecified.
22
- options.preview_paths << "#{Rails.root}/test/components/previews" if defined?(Rails.root) && Dir.exist?(
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.show_previews && !options.preview_paths.empty?
40
- paths_to_add = options.preview_paths - ActiveSupport::Dependencies.autoload_paths
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.show_previews
91
+ if options.previews.enabled
92
92
  app.routes.prepend do
93
- preview_controller = options.preview_controller.sub(/Controller$/, "").underscore
93
+ preview_controller = options.previews.controller.sub(/Controller$/, "").underscore
94
94
 
95
95
  get(
96
- options.preview_route,
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.preview_route}/*path",
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 inline_template
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)
@@ -102,7 +102,7 @@ module ViewComponent # :nodoc:
102
102
  private
103
103
 
104
104
  def preview_paths
105
- Base.preview_paths
105
+ Base.previews.paths
106
106
  end
107
107
  end
108
108
  end
@@ -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 !@content.nil?
46
+ return @content if defined?(@content)
52
47
 
53
48
  view_context = @parent.send(:view_context)
54
49
 
55
- if !@__vc_content_block.nil? && !@__vc_content_set_by_with_content.nil? && !@__vc_content_set_by_with_content.nil?
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 !@__vc_content_block.nil?
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 !@__vc_content.nil?
66
+ elsif defined?(@__vc_content)
72
67
  @__vc_content
73
- elsif !@__vc_content_block.nil?
68
+ elsif defined?(@__vc_content_block)
74
69
  view_context.capture(&@__vc_content_block)
75
- elsif !@__vc_content_set_by_with_content.nil?
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
- !@__vc_component_instance.nil?
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
- validate_singular_slot_name(slot_name)
76
+ __vc_validate_singular_slot_name(slot_name)
77
77
 
78
78
  if callable.is_a?(Hash) && callable.key?(:types)
79
- register_polymorphic_slot(slot_name, callable[:types], collection: false)
79
+ __vc_register_polymorphic_slot(slot_name, callable[:types], collection: false)
80
80
  else
81
- validate_plural_slot_name(ActiveSupport::Inflector.pluralize(slot_name).to_sym)
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
- set_slot(slot_name, nil, *args, **kwargs, &block)
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
- get_slot(slot_name)
90
+ __vc_get_slot(slot_name)
91
91
  end
92
92
 
93
93
  self::GeneratedSlotMethods.define_method :"#{slot_name}?" do
94
- get_slot(slot_name).present?
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
- register_slot(slot_name, collection: false, callable: callable)
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
- validate_plural_slot_name(slot_name)
145
+ __vc_validate_plural_slot_name(slot_name)
146
146
 
147
147
  if callable.is_a?(Hash) && callable.key?(:types)
148
- register_polymorphic_slot(slot_name, callable[:types], collection: true)
148
+ __vc_register_polymorphic_slot(slot_name, callable[:types], collection: true)
149
149
  else
150
150
  singular_name = ActiveSupport::Inflector.singularize(slot_name)
151
- validate_singular_slot_name(ActiveSupport::Inflector.singularize(slot_name).to_sym)
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
- set_slot(slot_name, nil, *args, **kwargs, &block)
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
- set_slot(slot_name, nil, **args, &block)
168
+ __vc_set_slot(slot_name, nil, **args, &block)
169
169
  else
170
- set_slot(slot_name, nil, *args, &block)
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
- get_slot(slot_name)
176
+ __vc_get_slot(slot_name)
177
177
  end
178
178
 
179
179
  self::GeneratedSlotMethods.define_method :"#{slot_name}?" do
180
- get_slot(slot_name).present?
180
+ __vc_get_slot(slot_name).present?
181
181
  end
182
182
 
183
- register_slot(slot_name, collection: true, callable: callable)
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 register_default_slots
216
+ def __vc_register_default_slots
216
217
  registered_slots.each do |slot_name, config|
217
- config[:default_method] = instance_methods.find { |method_name| method_name == :"default_#{slot_name}" }
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 register_slot(slot_name, **kwargs)
226
- registered_slots[slot_name] = define_slot(slot_name, **kwargs)
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 register_polymorphic_slot(slot_name, types, collection:)
231
+ def __vc_register_polymorphic_slot(slot_name, types, collection:)
230
232
  self::GeneratedSlotMethods.define_method(slot_name) do
231
- get_slot(slot_name)
233
+ __vc_get_slot(slot_name)
232
234
  end
233
235
 
234
236
  self::GeneratedSlotMethods.define_method(:"#{slot_name}?") do
235
- get_slot(slot_name).present?
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] = define_slot(
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
- set_polymorphic_slot(slot_name, poly_type, *args, **kwargs, &block)
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 define_slot(slot_name, collection:, callable:)
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 validate_plural_slot_name(slot_name)
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
- raise_if_slot_name_uncountable(slot_name)
310
- raise_if_slot_conflicts_with_call(slot_name)
311
- raise_if_slot_ends_with_question_mark(slot_name)
312
- raise_if_slot_registered(slot_name)
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 validate_singular_slot_name(slot_name)
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
- raise_if_slot_conflicts_with_call(slot_name)
325
- raise_if_slot_ends_with_question_mark(slot_name)
326
- raise_if_slot_registered(slot_name)
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 raise_if_slot_registered(slot_name)
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 raise_if_slot_ends_with_question_mark(slot_name)
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 raise_if_slot_conflicts_with_call(slot_name)
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 raise_if_slot_name_uncountable(slot_name)
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 get_slot(slot_name)
355
+ def __vc_get_slot(slot_name)
354
356
  @__vc_set_slots ||= {}
355
- content unless content_evaluated? # ensure content is loaded so slots will be defined
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 set_slot(slot_name, slot_definition = nil, *args, **kwargs, &block)
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 set_polymorphic_slot(slot_name, poly_type = nil, *args, **kwargs, &block)
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
- set_slot(slot_name, poly_def, *args, **kwargs, &block)
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, nil, nil)
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, nil, variant)
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
- maybe_escape_html(send(m)) do
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.preview_controller.constantize)
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(Base.test_controller.constantize)
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`: