view_component 2.64.0 → 2.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of view_component might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1cee1c1b53cec5fec9d4613416a27999c653c2cf8fb176798b235c7b71dc795d
4
- data.tar.gz: 5fb8a364788849fecfb8bb2160ebd6dc403f624ba6b3fe13c818706f928b8257
3
+ metadata.gz: 426a776552c0355ba0fb4ccc066c05a218b9998acb39489485375624b347c170
4
+ data.tar.gz: d17d69cb6e1c08fe31545eb5cf878579dd4aaf11e803790130c83ec7b4c178d2
5
5
  SHA512:
6
- metadata.gz: d721f8d07af64e314a506afc364941f95d3b824d27e587e12d8c774f4fa168b7ae00ac400c4f73b546ed0d5728aec60d586e52dacaee2b8f10e01230bbe3ab8f
7
- data.tar.gz: 598ab2f08524a8eb10b17a001ed7429223ca39ab204c25cec4375ea201e3afa1c852ba1578f81a1de5c83211e1eb05f3c1a7d146f83cc1d77e3f4ed0bfdef962
6
+ metadata.gz: 4b001cf58f8586b3e83cf8129c23d0bb5a499182189db4a99dfd747d6767f529a631eb2bf439a32f8a91dbb5861eb16ef637b514bffccacd476d577e2c5c27aa
7
+ data.tar.gz: 24d147cfbb226ff11114631721507bfed5a73fe25e1963186fe106a9c0f485596b65349457685967e7df0edea4d78841646f36683764244673e4281ff56741fd
@@ -10,9 +10,7 @@ module ViewComponent
10
10
  around_action :set_locale, only: :previews
11
11
  before_action :require_local!, unless: :show_previews?
12
12
 
13
- if respond_to?(:content_security_policy)
14
- content_security_policy(false)
15
- end
13
+ content_security_policy(false) if respond_to?(:content_security_policy)
16
14
  end
17
15
 
18
16
  def index
@@ -45,18 +43,18 @@ module ViewComponent
45
43
 
46
44
  # :doc:
47
45
  def default_preview_layout
48
- ViewComponent::Base.default_preview_layout
46
+ Rails.application.config.view_component.default_preview_layout
49
47
  end
50
48
 
51
49
  # :doc:
52
50
  def show_previews?
53
- ViewComponent::Base.show_previews
51
+ Rails.application.config.view_component.show_previews
54
52
  end
55
53
 
56
54
  # :doc:
57
55
  def find_preview
58
56
  candidates = []
59
- params[:path].to_s.scan(%r{/|$}) { candidates << $` }
57
+ params[:path].to_s.scan(%r{/|$}) { candidates << Regexp.last_match.pre_match }
60
58
  preview = candidates.detect { |candidate| ViewComponent::Preview.exists?(candidate) }
61
59
 
62
60
  if preview
@@ -66,10 +64,8 @@ module ViewComponent
66
64
  end
67
65
  end
68
66
 
69
- def set_locale
70
- I18n.with_locale(params[:locale] || I18n.default_locale) do
71
- yield
72
- end
67
+ def set_locale(&block)
68
+ I18n.with_locale(params[:locale] || I18n.default_locale, &block)
73
69
  end
74
70
 
75
71
  # Returns either {} or {layout: value} depending on configuration
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PreviewHelper
4
- AVAILABLE_PRISM_LANGUAGES = ["ruby", "erb", "haml"]
4
+ AVAILABLE_PRISM_LANGUAGES = %w[ruby erb haml]
5
5
  FALLBACK_LANGUAGE = "ruby"
6
6
 
7
7
  def preview_source
@@ -22,7 +22,7 @@ module PreviewHelper
22
22
  # Fetch template source via finding it through preview paths
23
23
  # to accomodate source view when exclusively using templates
24
24
  # for previews for Rails < 6.1.
25
- all_template_paths = ViewComponent::Base.preview_paths.map do |preview_path|
25
+ all_template_paths = Rails.application.config.view_component.preview_paths.map do |preview_path|
26
26
  Dir.glob("#{preview_path}/**/*")
27
27
  end.flatten
28
28
 
@@ -1,5 +1,5 @@
1
1
  <% if @render_args[:component] %>
2
- <% if ViewComponent::Base.render_monkey_patch_enabled || Rails.version.to_f >= 6.1 %>
2
+ <% if Rails.application.config.view_component.render_monkey_patch_enabled || Rails.version.to_f >= 6.1 %>
3
3
  <%= render(@render_args[:component], @render_args[:args], &@render_args[:block]) %>
4
4
  <% else %>
5
5
  <%= render_component(@render_args[:component], &@render_args[:block]) %>
@@ -8,6 +8,6 @@
8
8
  <%= render template: @render_args[:template], locals: @render_args[:locals] || {} %>
9
9
  <% end %>
10
10
 
11
- <% if ViewComponent::Base.show_previews_source %>
11
+ <% if Rails.application.config.view_component.show_previews_source %>
12
12
  <%= preview_source %>
13
13
  <% end %>
data/docs/CHANGELOG.md CHANGED
@@ -9,6 +9,27 @@ title: Changelog
9
9
 
10
10
  ## main
11
11
 
12
+ ## 2.66.0
13
+
14
+ * Add missing `generate.sidecar`, `generate.stimulus_controller`, `generate.locale`, `generate.distinct_locale_files`, `generate.preview` config options to `config.view_component`.
15
+
16
+ *Simon Fish*
17
+
18
+ ## 2.65.0
19
+
20
+ * Raise `ArgumentError` when conflicting Slots are defined.
21
+
22
+ Before this change it was possible to define Slots with conflicting names, for example:
23
+
24
+ ```ruby
25
+ class MyComponent < ViewComponent::Base
26
+ renders_one :item
27
+ renders_many :items
28
+ end
29
+ ```
30
+
31
+ *Joel Hawksley*
32
+
12
33
  ## 2.64.0
13
34
 
14
35
  * Add `warn_on_deprecated_slot_setter` flag to opt-in to deprecation warning.
@@ -3,9 +3,7 @@
3
3
  module ViewComponent
4
4
  module AbstractGenerator
5
5
  def copy_view_file
6
- unless options["inline"]
7
- template "component.html.#{engine_name}", destination
8
- end
6
+ template "component.html.#{engine_name}", destination unless options["inline"]
9
7
  end
10
8
 
11
9
  private
@@ -31,7 +29,7 @@ module ViewComponent
31
29
  end
32
30
 
33
31
  def component_path
34
- ViewComponent::Base.view_component_path
32
+ Rails.application.config.view_component.view_component_path
35
33
  end
36
34
 
37
35
  def stimulus_controller
@@ -44,7 +42,7 @@ module ViewComponent
44
42
  end
45
43
 
46
44
  def sidecar?
47
- options["sidecar"] || ViewComponent::Base.generate.sidecar
45
+ options["sidecar"] || Rails.application.config.view_component.generate.sidecar
48
46
  end
49
47
  end
50
48
  end
@@ -13,11 +13,12 @@ module Rails
13
13
  check_class_collision suffix: "Component"
14
14
 
15
15
  class_option :inline, type: :boolean, default: false
16
- class_option :locale, type: :boolean, default: ViewComponent::Base.generate.locale
16
+ class_option :locale, type: :boolean, default: Rails.application.config.view_component.generate.locale
17
17
  class_option :parent, type: :string, desc: "The parent class for the generated component"
18
- class_option :preview, type: :boolean, default: ViewComponent::Base.generate.preview
18
+ class_option :preview, type: :boolean, default: Rails.application.config.view_component.generate.preview
19
19
  class_option :sidecar, type: :boolean, default: false
20
- class_option :stimulus, type: :boolean, default: ViewComponent::Base.generate.stimulus_controller
20
+ class_option :stimulus, type: :boolean,
21
+ default: Rails.application.config.view_component.generate.stimulus_controller
21
22
 
22
23
  def create_component_file
23
24
  template "component.rb", File.join(component_path, class_path, "#{file_name}_component.rb")
@@ -40,7 +41,7 @@ module Rails
40
41
  def parent_class
41
42
  return options[:parent] if options[:parent]
42
43
 
43
- ViewComponent::Base.component_parent_class || default_parent_class
44
+ Rails.application.config.view_component.component_parent_class || default_parent_class
44
45
  end
45
46
 
46
47
  def initialize_signature
@@ -12,7 +12,7 @@ module Locale
12
12
  class_option :sidecar, type: :boolean, default: false
13
13
 
14
14
  def create_locale_file
15
- if ViewComponent::Base.generate.distinct_locale_files
15
+ if Rails.application.config.view_component.generate.distinct_locale_files
16
16
  I18n.available_locales.each do |locale|
17
17
  create_file destination(locale), translations_hash([locale]).to_yaml
18
18
  end
@@ -4,9 +4,9 @@ require "action_view"
4
4
  require "active_support/configurable"
5
5
  require "view_component/collection"
6
6
  require "view_component/compile_cache"
7
+ require "view_component/config"
7
8
  require "view_component/content_areas"
8
9
  require "view_component/polymorphic_slots"
9
- require "view_component/previewable"
10
10
  require "view_component/slotable"
11
11
  require "view_component/slotable_v2"
12
12
  require "view_component/translatable"
@@ -14,10 +14,16 @@ require "view_component/with_content_helper"
14
14
 
15
15
  module ViewComponent
16
16
  class Base < ActionView::Base
17
- include ActiveSupport::Configurable
17
+ class << self
18
+ delegate(*ViewComponent::Config.defaults.keys, to: :config)
19
+
20
+ def config
21
+ Rails.application.config.view_component
22
+ end
23
+ end
24
+
18
25
  include ViewComponent::ContentAreas
19
26
  include ViewComponent::PolymorphicSlots
20
- include ViewComponent::Previewable
21
27
  include ViewComponent::SlotableV2
22
28
  include ViewComponent::Translatable
23
29
  include ViewComponent::WithContentHelper
@@ -113,11 +119,9 @@ module ViewComponent
113
119
  @current_template = self
114
120
 
115
121
  if block && defined?(@__vc_content_set_by_with_content)
116
- raise ArgumentError.new(
117
- "It looks like a block was provided after calling `with_content` on #{self.class.name}, " \
122
+ raise ArgumentError, "It looks like a block was provided after calling `with_content` on #{self.class.name}, " \
118
123
  "which means that ViewComponent doesn't know which content to use.\n\n" \
119
124
  "To fix this issue, use either `with_content` or a block."
120
- )
121
125
  end
122
126
 
123
127
  @__vc_content_evaluated = false
@@ -262,9 +266,7 @@ module ViewComponent
262
266
  # @private
263
267
  def format
264
268
  # Ruby 2.6 throws a warning without checking `defined?`, 2.7 doesn't
265
- if defined?(@__vc_variant)
266
- @__vc_variant
267
- end
269
+ @__vc_variant if defined?(@__vc_variant)
268
270
  end
269
271
 
270
272
  # Use the provided variant instead of the one determined by the current request.
@@ -313,11 +315,9 @@ module ViewComponent
313
315
  # config.view_component.test_controller = "MyTestController"
314
316
  # ```
315
317
  #
316
- # Defaults to ApplicationController. Can also be configured on a per-test
317
- # basis using `with_controller_class`.
318
+ # Defaults to `nil`. If this is falsy, `"ApplicationController"` is used. Can also be
319
+ # configured on a per-test basis using `with_controller_class`.
318
320
  #
319
- mattr_accessor :test_controller
320
- @@test_controller = "ApplicationController"
321
321
 
322
322
  # Set if render monkey patches should be included or not in Rails <6.1:
323
323
  #
@@ -325,7 +325,6 @@ module ViewComponent
325
325
  # config.view_component.render_monkey_patch_enabled = false
326
326
  # ```
327
327
  #
328
- mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
329
328
 
330
329
  # Path for component files
331
330
  #
@@ -333,9 +332,8 @@ module ViewComponent
333
332
  # config.view_component.view_component_path = "app/my_components"
334
333
  # ```
335
334
  #
336
- # Defaults to `app/components`.
335
+ # Defaults to `nil`. If this is falsy, `app/components` is used.
337
336
  #
338
- mattr_accessor :view_component_path, instance_writer: false, default: "app/components"
339
337
 
340
338
  # Parent class for generated components
341
339
  #
@@ -346,7 +344,6 @@ module ViewComponent
346
344
  # Defaults to nil. If this is falsy, generators will use
347
345
  # "ApplicationComponent" if defined, "ViewComponent::Base" otherwise.
348
346
  #
349
- mattr_accessor :component_parent_class, instance_writer: false
350
347
 
351
348
  # Configuration for generators.
352
349
  #
@@ -397,7 +394,6 @@ module ViewComponent
397
394
  # ```
398
395
  #
399
396
  # Defaults to `false`.
400
- mattr_accessor :generate, instance_writer: false, default: ActiveSupport::OrderedOptions.new(false)
401
397
 
402
398
  class << self
403
399
  # @private
@@ -489,8 +485,8 @@ module ViewComponent
489
485
 
490
486
  # If Rails application is loaded, add application url_helpers to the component context
491
487
  # we need to check this to use this gem as a dependency
492
- if defined?(Rails) && Rails.application
493
- child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers
488
+ if defined?(Rails) && Rails.application && !(child < Rails.application.routes.url_helpers)
489
+ child.include Rails.application.routes.url_helpers
494
490
  end
495
491
 
496
492
  # Derive the source location of the component Ruby file from the call stack.
@@ -500,7 +496,7 @@ module ViewComponent
500
496
 
501
497
  # Removes the first part of the path and the extension.
502
498
  child.virtual_path = child.source_location.gsub(
503
- %r{(.*#{Regexp.quote(ViewComponent::Base.view_component_path)})|(\.rb)}, ""
499
+ /(.*#{Regexp.quote(Rails.application.config.view_component.view_component_path)})|(\.rb)/, ""
504
500
  )
505
501
 
506
502
  # Set collection parameter to the extended component
@@ -591,20 +587,16 @@ module ViewComponent
591
587
  # parameters will be empty and ViewComponent will not be able to render
592
588
  # the component.
593
589
  if initialize_parameters.empty?
594
- raise ArgumentError.new(
595
- "The #{self} initializer is empty or invalid." \
590
+ raise ArgumentError, "The #{self} initializer is empty or invalid." \
596
591
  "It must accept the parameter `#{parameter}` to render it as a collection.\n\n" \
597
592
  "To fix this issue, update the initializer to accept `#{parameter}`.\n\n" \
598
593
  "See https://viewcomponent.org/guide/collections.html for more information on rendering collections."
599
- )
600
594
  end
601
595
 
602
- raise ArgumentError.new(
603
- "The initializer for #{self} doesn't accept the parameter `#{parameter}`, " \
596
+ raise ArgumentError, "The initializer for #{self} doesn't accept the parameter `#{parameter}`, " \
604
597
  "which is required in order to render it as a collection.\n\n" \
605
598
  "To fix this issue, update the initializer to accept `#{parameter}`.\n\n" \
606
599
  "See https://viewcomponent.org/guide/collections.html for more information on rendering collections."
607
- )
608
600
  end
609
601
 
610
602
  # Ensure the component initializer doesn't define
@@ -614,10 +606,8 @@ module ViewComponent
614
606
  def validate_initialization_parameters!
615
607
  return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
616
608
 
617
- raise ViewComponent::ComponentError.new(
618
- "#{self} initializer can't accept the parameter `#{RESERVED_PARAMETER}`, as it will override a " \
609
+ raise ViewComponent::ComponentError, "#{self} initializer can't accept the parameter `#{RESERVED_PARAMETER}`, as it will override a " \
619
610
  "public ViewComponent method. To fix this issue, rename the parameter."
620
- )
621
611
  end
622
612
 
623
613
  # @private
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "view_component/deprecation"
4
+
5
+ module ViewComponent
6
+ class Config
7
+ class << self
8
+ # `new` without any arguments initializes the default configuration, but
9
+ # it's important to differentiate in case that's no longer the case in
10
+ # future.
11
+ alias_method :default, :new
12
+
13
+ def defaults
14
+ ActiveSupport::OrderedOptions.new.merge!({
15
+ generate: ActiveSupport::OrderedOptions.new(false),
16
+ preview_controller: "ViewComponentsController",
17
+ preview_route: "/rails/view_components",
18
+ show_previews_source: false,
19
+ instrumentation_enabled: false,
20
+ render_monkey_patch_enabled: true,
21
+ view_component_path: "app/components",
22
+ component_parent_class: nil,
23
+ show_previews: Rails.env.development? || Rails.env.test?,
24
+ preview_paths: default_preview_paths,
25
+ test_controller: "ApplicationController",
26
+ default_preview_layout: nil
27
+ })
28
+ end
29
+
30
+ # @!attribute generate
31
+ # @return [ActiveSupport::OrderedOptions]
32
+ # The subset of configuration options relating to generators.
33
+ #
34
+ # All options under this namespace default to `false` unless otherwise
35
+ # stated.
36
+ #
37
+ # #### #sidecar
38
+ #
39
+ # Always generate a component with a sidecar directory:
40
+ #
41
+ # config.view_component.generate.sidecar = true
42
+ #
43
+ # #### #stimulus_controller
44
+ #
45
+ # Always generate a Stimulus controller alongside the component:
46
+ #
47
+ # config.view_component.generate.stimulus_controller = true
48
+ #
49
+ # #### #locale
50
+ #
51
+ # Always generate translations file alongside the component:
52
+ #
53
+ # config.view_component.generate.locale = true
54
+ #
55
+ # #### #distinct_locale_files
56
+ #
57
+ # Always generate as many translations files as available locales:
58
+ #
59
+ # config.view_component.generate.distinct_locale_files = true
60
+ #
61
+ # One file will be generated for each configured `I18n.available_locales`,
62
+ # falling back to `[:en]` when no `available_locales` is defined.
63
+ #
64
+ # #### #preview
65
+ #
66
+ # Always generate a preview alongside the component:
67
+ #
68
+ # config.view_component.generate.preview = true
69
+
70
+ # @!attribute preview_controller
71
+ # @return [String]
72
+ # The controller used for previewing components.
73
+ # Defaults to `ViewComponentsController`.
74
+
75
+ # @!attribute preview_route
76
+ # @return [String]
77
+ # The entry route for component previews.
78
+ # Defaults to `"/rails/view_components"`.
79
+
80
+ # @!attribute show_previews_source
81
+ # @return [Boolean]
82
+ # Whether to display source code previews in component previews.
83
+ # Defaults to `false`.
84
+
85
+ # @!attribute instrumentation_enabled
86
+ # @return [Boolean]
87
+ # Whether ActiveSupport notifications are enabled.
88
+ # Defaults to `false`.
89
+
90
+ # @!attribute render_monkey_patch_enabled
91
+ # @return [Boolean] Whether the #render method should be monkey patched.
92
+ # If this is disabled, use `#render_component` or
93
+ # `#render_component_to_string` instead.
94
+ # Defaults to `true`.
95
+
96
+ # @!attribute view_component_path
97
+ # @return [String]
98
+ # The path in which components, their templates, and their sidecars should
99
+ # be stored.
100
+ # Defaults to `"app/components"`.
101
+
102
+ # @!attribute component_parent_class
103
+ # @return [String]
104
+ # The parent class from which generated components will inherit.
105
+ # Defaults to `nil`. If this is falsy, generators will use
106
+ # `"ApplicationComponent"` if defined, `"ViewComponent::Base"` otherwise.
107
+
108
+ # @!attribute show_previews
109
+ # @return [Boolean]
110
+ # Whether component previews are enabled.
111
+ # Defaults to `true` in development and test environments.
112
+
113
+ # @!attribute preview_paths
114
+ # @return [Array<String>]
115
+ # The locations in which component previews will be looked up.
116
+ # Defaults to `['test/component/previews']` relative to your Rails root.
117
+
118
+ # @!attribute preview_path
119
+ # @deprecated Use #preview_paths instead. Will be removed in v3.0.0.
120
+
121
+ # @!attribute test_controller
122
+ # @return [String]
123
+ # The controller used for testing components.
124
+ # Can also be configured on a per-test basis using `#with_controller_class`.
125
+ # Defaults to `ApplicationController`.
126
+
127
+ # @!attribute default_preview_layout
128
+ # @return [String]
129
+ # A custom default layout used for the previews index page and individual
130
+ # previews.
131
+ # Defaults to `nil`. If this is falsy, `"component_preview"` is used.
132
+
133
+ def default_preview_paths
134
+ return [] unless defined?(Rails.root) && Dir.exist?("#{Rails.root}/test/components/previews")
135
+
136
+ ["#{Rails.root}/test/components/previews"]
137
+ end
138
+ end
139
+
140
+ def initialize
141
+ @config = self.class.defaults
142
+ end
143
+
144
+ def preview_path
145
+ preview_paths
146
+ end
147
+
148
+ def preview_path=(new_value)
149
+ ViewComponent::Deprecation.warn("`preview_path` will be removed in v3.0.0. Use `preview_paths` instead.")
150
+ self.preview_paths = Array.wrap(new_value)
151
+ end
152
+
153
+ delegate_missing_to :config
154
+
155
+ private
156
+
157
+ attr_reader :config
158
+ end
159
+ end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails"
4
+ require "view_component/base"
4
5
 
5
6
  module ViewComponent
6
7
  class Engine < Rails::Engine # :nodoc:
7
- config.view_component = ActiveSupport::OrderedOptions.new
8
- config.view_component.preview_paths ||= []
8
+ config.view_component = ViewComponent::Config.default
9
9
 
10
10
  rake_tasks do
11
11
  load "view_component/rails/tasks/view_component.rake"
@@ -14,25 +14,20 @@ module ViewComponent
14
14
  initializer "view_component.set_configs" do |app|
15
15
  options = app.config.view_component
16
16
 
17
+ %i[generate preview_controller preview_route show_previews_source].each do |config_option|
18
+ options[config_option] ||= ViewComponent::Base.public_send(config_option)
19
+ end
20
+ options.instrumentation_enabled = false if options.instrumentation_enabled.nil?
17
21
  options.render_monkey_patch_enabled = true if options.render_monkey_patch_enabled.nil?
18
22
  options.show_previews = Rails.env.development? || Rails.env.test? if options.show_previews.nil?
19
- options.show_previews_source ||= ViewComponent::Base.show_previews_source
20
23
  options.instrumentation_enabled = false if options.instrumentation_enabled.nil?
21
- options.preview_route ||= ViewComponent::Base.preview_route
22
- options.preview_controller ||= ViewComponent::Base.preview_controller
23
24
 
24
25
  if options.show_previews
26
+ # This is still necessary because when `config.view_component` is declared, `Rails.root` is unspecified.
25
27
  options.preview_paths << "#{Rails.root}/test/components/previews" if defined?(Rails.root) && Dir.exist?(
26
28
  "#{Rails.root}/test/components/previews"
27
29
  )
28
30
 
29
- if options.preview_path.present?
30
- ViewComponent::Deprecation.warn(
31
- "`preview_path` will be removed in v3.0.0. Use `preview_paths` instead."
32
- )
33
- options.preview_paths << options.preview_path
34
- end
35
-
36
31
  if options.show_previews_source
37
32
  require "method_source"
38
33
 
@@ -41,10 +36,6 @@ module ViewComponent
41
36
  end
42
37
  end
43
38
  end
44
-
45
- ActiveSupport.on_load(:view_component) do
46
- options.each { |k, v| send("#{k}=", v) if respond_to?("#{k}=") }
47
- end
48
39
  end
49
40
 
50
41
  initializer "view_component.enable_instrumentation" do |app|
@@ -72,12 +63,6 @@ module ViewComponent
72
63
  end
73
64
  end
74
65
 
75
- initializer "view_component.compile_config_methods" do
76
- ActiveSupport.on_load(:view_component) do
77
- config.compile_methods! if config.respond_to?(:compile_methods!)
78
- end
79
- end
80
-
81
66
  initializer "view_component.monkey_patch_render" do |app|
82
67
  next if Rails.version.to_f >= 6.1 || !app.config.view_component.render_monkey_patch_enabled
83
68
 
@@ -94,7 +79,7 @@ module ViewComponent
94
79
  end
95
80
  end
96
81
 
97
- initializer "view_component.include_render_component" do |app|
82
+ initializer "view_component.include_render_component" do |_app|
98
83
  next if Rails.version.to_f >= 6.1
99
84
 
100
85
  ActiveSupport.on_load(:action_view) do
@@ -116,7 +101,7 @@ module ViewComponent
116
101
  end
117
102
  end
118
103
 
119
- initializer "compiler mode" do |app|
104
+ initializer "compiler mode" do |_app|
120
105
  ViewComponent::Compiler.mode = if Rails.env.development? || Rails.env.test?
121
106
  ViewComponent::Compiler::DEVELOPMENT_MODE
122
107
  else
@@ -160,7 +145,7 @@ unless defined?(ViewComponent::Base)
160
145
 
161
146
  ViewComponent::Deprecation.warn(
162
147
  "This manually engine loading is deprecated and will be removed in v3.0.0. " \
163
- "Remove `require \"view_component/engine\"`."
148
+ 'Remove `require "view_component/engine"`.'
164
149
  )
165
150
 
166
151
  require "view_component"
@@ -22,9 +22,7 @@ module ViewComponent
22
22
  def render_preview(name)
23
23
  begin
24
24
  preview_klass = if respond_to?(:described_class)
25
- if described_class.nil?
26
- raise "`render_preview` expected a described_class, but it is nil."
27
- end
25
+ raise "`render_preview` expected a described_class, but it is nil." if described_class.nil?
28
26
 
29
27
  "#{described_class}Preview"
30
28
  else
@@ -32,12 +30,10 @@ module ViewComponent
32
30
  end
33
31
  preview_klass = preview_klass.constantize
34
32
  rescue NameError
35
- raise NameError.new(
36
- "`render_preview` expected to find #{preview_klass}, but it does not exist."
37
- )
33
+ raise NameError, "`render_preview` expected to find #{preview_klass}, but it does not exist."
38
34
  end
39
35
 
40
- previews_controller = build_controller(ViewComponent::Base.preview_controller.constantize)
36
+ previews_controller = build_controller(Rails.application.config.view_component.preview_controller.constantize)
41
37
  previews_controller.request.params[:path] = "#{preview_klass.preview_name}/#{name}"
42
38
  previews_controller.response = ActionDispatch::Response.new
43
39
  result = previews_controller.previews
@@ -80,6 +80,7 @@ module ViewComponent
80
80
  # <% end %>
81
81
  def renders_one(slot_name, callable = nil)
82
82
  validate_singular_slot_name(slot_name)
83
+ validate_plural_slot_name(ActiveSupport::Inflector.pluralize(slot_name).to_sym)
83
84
 
84
85
  define_method :"with_#{slot_name}" do |*args, &block|
85
86
  set_slot(slot_name, nil, *args, &block)
@@ -147,9 +148,9 @@ module ViewComponent
147
148
  # <% end %>
148
149
  # <% end %>
149
150
  def renders_many(slot_name, callable = nil)
150
- validate_plural_slot_name(slot_name)
151
-
152
151
  singular_name = ActiveSupport::Inflector.singularize(slot_name)
152
+ validate_plural_slot_name(slot_name)
153
+ validate_singular_slot_name(ActiveSupport::Inflector.singularize(slot_name).to_sym)
153
154
 
154
155
  # Define setter for singular names
155
156
  # for example `renders_many :items` allows fetching all tabs with
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 64
6
+ MINOR = 66
7
7
  PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
@@ -10,6 +10,7 @@ module ViewComponent
10
10
  autoload :Compiler
11
11
  autoload :CompileCache
12
12
  autoload :ComponentError
13
+ autoload :Config
13
14
  autoload :Deprecation
14
15
  autoload :Instrumentation
15
16
  autoload :Preview
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.64.0
4
+ version: 2.66.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: 2022-08-03 00:00:00.000000000 Z
11
+ date: 2022-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -357,6 +357,7 @@ files:
357
357
  - lib/view_component/compile_cache.rb
358
358
  - lib/view_component/compiler.rb
359
359
  - lib/view_component/component_error.rb
360
+ - lib/view_component/config.rb
360
361
  - lib/view_component/content_areas.rb
361
362
  - lib/view_component/deprecation.rb
362
363
  - lib/view_component/docs_builder_component.html.erb
@@ -366,7 +367,6 @@ files:
366
367
  - lib/view_component/polymorphic_slots.rb
367
368
  - lib/view_component/preview.rb
368
369
  - lib/view_component/preview_template_error.rb
369
- - lib/view_component/previewable.rb
370
370
  - lib/view_component/rails/tasks/view_component.rake
371
371
  - lib/view_component/render_component_helper.rb
372
372
  - lib/view_component/render_component_to_string_helper.rb
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_support/concern"
4
-
5
- module ViewComponent
6
- module Previewable
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- # Enable or disable component previews:
11
- #
12
- # config.view_component.show_previews = true
13
- #
14
- # Defaults to `true` in development.
15
- #
16
- mattr_accessor :show_previews, instance_writer: false
17
-
18
- # Enable or disable source code previews in component previews:
19
- #
20
- # config.view_component.show_previews_source = true
21
- #
22
- # Defaults to `false`.
23
- #
24
- mattr_accessor :show_previews_source, instance_writer: false, default: false
25
-
26
- # Set a custom default layout used for preview index and individual previews:
27
- #
28
- # config.view_component.default_preview_layout = "component_preview"
29
- #
30
- mattr_accessor :default_preview_layout, instance_writer: false
31
-
32
- # Set the location of component previews:
33
- #
34
- # config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
35
- #
36
- mattr_accessor :preview_paths, instance_writer: false
37
-
38
- # @deprecated Use `preview_paths` instead. Will be removed in v3.0.0.
39
- mattr_accessor :preview_path, instance_writer: false
40
-
41
- # Set the entry route for component previews:
42
- #
43
- # config.view_component.preview_route = "/previews"
44
- #
45
- # Defaults to `/rails/view_components` when `show_previews` is enabled.
46
- #
47
- mattr_accessor :preview_route, instance_writer: false do
48
- "/rails/view_components"
49
- end
50
-
51
- # Set the controller used for previewing components:
52
- #
53
- # config.view_component.preview_controller = "MyPreviewController"
54
- #
55
- # Defaults to `ViewComponentsController`.
56
- #
57
- mattr_accessor :preview_controller, instance_writer: false do
58
- "ViewComponentsController"
59
- end
60
- end
61
- end
62
- end