view_component 2.17.0 → 2.19.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.

@@ -16,22 +16,23 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
16
16
  def index
17
17
  @previews = ViewComponent::Preview.all
18
18
  @page_title = "Component Previews"
19
+ render "view_components/index", **determine_layout
19
20
  end
20
21
 
21
22
  def previews
22
23
  if params[:path] == @preview.preview_name
23
24
  @page_title = "Component Previews for #{@preview.preview_name}"
24
- render "view_components/previews"
25
+ render "view_components/previews", **determine_layout
25
26
  else
26
27
  prepend_application_view_paths
27
28
  prepend_preview_examples_view_path
28
29
  @example_name = File.basename(params[:path])
29
30
  @render_args = @preview.render_args(@example_name, params: params.permit!)
30
- layout = @render_args[:layout]
31
+ layout = determine_layout(@render_args[:layout], prepend_views: false)[:layout]
31
32
  template = @render_args[:template]
32
33
  locals = @render_args[:locals]
33
34
  opts = {}
34
- opts[:layout] = layout if layout.present?
35
+ opts[:layout] = layout if layout.present? || layout == false
35
36
  opts[:locals] = locals if locals.present?
36
37
  render template, opts # rubocop:disable GitHub/RailsControllerRenderLiteral
37
38
  end
@@ -39,6 +40,10 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
39
40
 
40
41
  private
41
42
 
43
+ def default_preview_layout # :doc:
44
+ ViewComponent::Base.default_preview_layout
45
+ end
46
+
42
47
  def show_previews? # :doc:
43
48
  ViewComponent::Base.show_previews
44
49
  end
@@ -61,6 +66,24 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
61
66
  end
62
67
  end
63
68
 
69
+ # Returns either {} or {layout: value} depending on configuration
70
+ def determine_layout(layout_override = nil, prepend_views: true)
71
+ return {} unless defined?(Rails.root)
72
+
73
+ layout_declaration = {}
74
+
75
+ if !layout_override.nil?
76
+ # Allow component-level override, even if false (thus no layout rendered)
77
+ layout_declaration[:layout] = layout_override
78
+ elsif default_preview_layout.present?
79
+ layout_declaration[:layout] = default_preview_layout
80
+ end
81
+
82
+ prepend_application_view_paths if layout_declaration[:layout].present? && prepend_views
83
+
84
+ layout_declaration
85
+ end
86
+
64
87
  def prepend_application_view_paths
65
88
  prepend_view_path Rails.root.join("app/views") if defined?(Rails.root)
66
89
  end
@@ -1 +1,5 @@
1
- <%= render(@render_args[:component], @render_args[:args], &@render_args[:block])%>
1
+ <% if ViewComponent::Base.render_monkey_patch_enabled || Rails.version.to_f >= 6.1 %>
2
+ <%= render(@render_args[:component], @render_args[:args], &@render_args[:block])%>
3
+ <% else %>
4
+ <%= render_component(@render_args[:component], &@render_args[:block])%>
5
+ <% end %>
@@ -12,6 +12,8 @@ module ViewComponent
12
12
  include ActiveSupport::Configurable
13
13
  include ViewComponent::Previewable
14
14
 
15
+ ViewContextCalledBeforeRenderError = Class.new(StandardError)
16
+
15
17
  # For CSRF authenticity tokens in forms
16
18
  delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
17
19
 
@@ -108,17 +110,19 @@ module ViewComponent
108
110
  end
109
111
 
110
112
  def controller
113
+ raise ViewContextCalledBeforeRenderError, "`controller` can only be called at render time." if view_context.nil?
111
114
  @controller ||= view_context.controller
112
115
  end
113
116
 
114
117
  # Provides a proxy to access helper methods from the context of the current controller
115
118
  def helpers
119
+ raise ViewContextCalledBeforeRenderError, "`helpers` can only be called at render time." if view_context.nil?
116
120
  @helpers ||= controller.view_context
117
121
  end
118
122
 
119
- # Removes the first part of the path and the extension.
123
+ # Exposes .virutal_path as an instance method
120
124
  def virtual_path
121
- self.class.source_location.gsub(%r{(.*app/components)|(\.rb)}, "")
125
+ self.class.virtual_path
122
126
  end
123
127
 
124
128
  # For caching, such as #cache_if
@@ -166,7 +170,7 @@ module ViewComponent
166
170
  mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
167
171
 
168
172
  class << self
169
- attr_accessor :source_location
173
+ attr_accessor :source_location, :virtual_path
170
174
 
171
175
  # Render a component collection.
172
176
  def with_collection(collection, **args)
@@ -179,6 +183,10 @@ module ViewComponent
179
183
  end
180
184
 
181
185
  def inherited(child)
186
+ # Compile so child will inherit compiled `call_*` template methods that
187
+ # `compile` defines
188
+ compile
189
+
182
190
  # If we're in Rails, add application url_helpers to the component context
183
191
  if defined?(Rails)
184
192
  child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers
@@ -189,6 +197,9 @@ module ViewComponent
189
197
  # has been re-defined by the consuming application, likely in ApplicationComponent.
190
198
  child.source_location = caller_locations(1, 10).reject { |l| l.label == "inherited" }[0].absolute_path
191
199
 
200
+ # Removes the first part of the path and the extension.
201
+ child.virtual_path = child.source_location.gsub(%r{(.*app/components)|(\.rb)}, "")
202
+
192
203
  # Clone slot configuration into child class
193
204
  # see #test_slots_pollution
194
205
  child.slots = self.slots.clone
@@ -378,17 +389,17 @@ module ViewComponent
378
389
 
379
390
  location_without_extension = source_location.chomp(File.extname(source_location))
380
391
 
381
- extenstions = ActionView::Template.template_handler_extensions.join(",")
392
+ extensions = ActionView::Template.template_handler_extensions.join(",")
382
393
 
383
- # view files in the same directory as te component
384
- sidecar_files = Dir["#{location_without_extension}.*{#{extenstions}}"]
394
+ # view files in the same directory as the component
395
+ sidecar_files = Dir["#{location_without_extension}.*{#{extensions}}"]
385
396
 
386
397
  # view files in a directory named like the component
387
398
  directory = File.dirname(source_location)
388
399
  filename = File.basename(source_location, ".rb")
389
400
  component_name = name.demodulize.underscore
390
401
 
391
- sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extenstions}}"]
402
+ sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extensions}}"]
392
403
 
393
404
  (sidecar_files - [source_location] + sidecar_directory_files)
394
405
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "action_view/renderer/collection_renderer" if Rails.version.to_f >= 6.1
4
+
3
5
  module ViewComponent
4
6
  class Collection
5
7
  def render_in(view_context, &block)
@@ -34,8 +34,8 @@ module ViewComponent
34
34
  initializer "view_component.set_autoload_paths" do |app|
35
35
  options = app.config.view_component
36
36
 
37
- if options.show_previews && options.preview_path
38
- ActiveSupport::Dependencies.autoload_paths << options.preview_path
37
+ if options.show_previews && !options.preview_paths.empty?
38
+ ActiveSupport::Dependencies.autoload_paths.concat(options.preview_paths)
39
39
  end
40
40
  end
41
41
 
@@ -24,6 +24,8 @@ module ViewComponent # :nodoc:
24
24
  }
25
25
  end
26
26
 
27
+ alias_method :render_component, :render
28
+
27
29
  class << self
28
30
  # Returns all component preview classes.
29
31
  def all
@@ -42,21 +44,11 @@ module ViewComponent # :nodoc:
42
44
  result.merge(layout: @layout)
43
45
  end
44
46
 
45
- # Returns the component object class associated to the preview.
46
- def component
47
- name.chomp("Preview").constantize
48
- end
49
-
50
47
  # Returns all of the available examples for the component preview.
51
48
  def examples
52
49
  public_instance_methods(false).map(&:to_s).sort
53
50
  end
54
51
 
55
- # Returns +true+ if the example of the component preview exists.
56
- def example_exists?(example)
57
- examples.include?(example)
58
- end
59
-
60
52
  # Returns +true+ if the preview exists.
61
53
  def exists?(preview)
62
54
  all.any? { |p| p.preview_name == preview }
@@ -102,10 +94,6 @@ module ViewComponent # :nodoc:
102
94
  def preview_paths
103
95
  Base.preview_paths
104
96
  end
105
-
106
- def show_previews
107
- Base.show_previews
108
- end
109
97
  end
110
98
  end
111
99
  end
@@ -7,6 +7,14 @@ module ViewComponent # :nodoc:
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
+ # Set a custom default preview layout through app configuration:
11
+ #
12
+ # config.view_component.default_preview_layout = "component_preview"
13
+ #
14
+ # This affects preview index pages as well as individual component previews
15
+ #
16
+ mattr_accessor :default_preview_layout, instance_writer: false
17
+
10
18
  # Set the location of component previews through app configuration:
11
19
  #
12
20
  # config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
@@ -98,7 +98,7 @@ module ViewComponent
98
98
  slot_instance = args.present? ? slot_class.new(**args) : slot_class.new
99
99
 
100
100
  # Capture block and assign to slot_instance#content
101
- slot_instance.content = view_context.capture(&block).strip.html_safe if block_given?
101
+ slot_instance.content = view_context.capture(&block).to_s.strip.html_safe if block_given?
102
102
 
103
103
  if slot[:collection]
104
104
  # Initialize instance variable as an empty array
@@ -14,7 +14,11 @@ module ViewComponent
14
14
  assert_no_selector("body")
15
15
  end
16
16
  rescue LoadError
17
+ # We don't have a test case for running an application without capybara installed.
18
+ # It's probably fine to leave this without coverage.
19
+ # :nocov:
17
20
  warn "WARNING in `ViewComponent::TestHelpers`: You must add `capybara` to your Gemfile to use Capybara assertions." if ENV["DEBUG"]
21
+ # :nocov:
18
22
  end
19
23
 
20
24
  attr_reader :rendered_component
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 17
6
+ MINOR = 19
7
7
  PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
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.17.0
4
+ version: 2.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-21 00:00:00.000000000 Z
11
+ date: 2020-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '7.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: benchmark-ips
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.8.2
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.8.2
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: bundler
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -157,20 +171,20 @@ dependencies:
157
171
  - !ruby/object:Gem::Version
158
172
  version: 0.18.0
159
173
  - !ruby/object:Gem::Dependency
160
- name: simplecov-erb
174
+ name: simplecov-console
161
175
  requirement: !ruby/object:Gem::Requirement
162
176
  requirements:
163
177
  - - "~>"
164
178
  - !ruby/object:Gem::Version
165
- version: '0.1'
179
+ version: 0.7.2
166
180
  type: :development
167
181
  prerelease: false
168
182
  version_requirements: !ruby/object:Gem::Requirement
169
183
  requirements:
170
184
  - - "~>"
171
185
  - !ruby/object:Gem::Version
172
- version: '0.1'
173
- description:
186
+ version: 0.7.2
187
+ description:
174
188
  email:
175
189
  - opensource+view_component@github.com
176
190
  executables: []
@@ -222,7 +236,7 @@ licenses:
222
236
  - MIT
223
237
  metadata:
224
238
  allowed_push_host: https://rubygems.org
225
- post_install_message:
239
+ post_install_message:
226
240
  rdoc_options: []
227
241
  require_paths:
228
242
  - lib
@@ -238,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
252
  version: '0'
239
253
  requirements: []
240
254
  rubygems_version: 3.1.2
241
- signing_key:
255
+ signing_key:
242
256
  specification_version: 4
243
257
  summary: View components for Rails
244
258
  test_files: []