view_component 2.18.1 → 2.18.2
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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +49 -16
- data/lib/view_component/base.rb +8 -4
- data/lib/view_component/preview.rb +0 -14
- data/lib/view_component/test_helpers.rb +4 -0
- data/lib/view_component/version.rb +1 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2198b33fb53185423a45c6f13023650604e7dacc2f5b44c2455f44b684ffdbc
|
4
|
+
data.tar.gz: f9eaffd030eb7bef12b243cfdf42333e4f5b28bf6a975f6b4720b65ef0d6aedc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ab6f420e32b85e912b4407ab3679e3fd696800547aecaa13c15c7833c82564f7ba8bc7db4fad8dbd7aa201250db156901486ee3c12b13f37ffedca3e5cbacf1
|
7
|
+
data.tar.gz: 22103cb47921ba57712808c6a3130f48926a40179a3564fab9b2235dc892edde3ed81df28e6c23535685d13121b4be1f232836612e7132d4be04143595eebb6d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# master
|
2
2
|
|
3
|
+
# 2.18.2
|
4
|
+
|
5
|
+
* Raise an error if controller or view context is accessed during initialize as they are only available in render.
|
6
|
+
|
7
|
+
*Julian Nadeau*
|
8
|
+
|
9
|
+
* Collate test coverage across CI builds, ensuring 100% test coverage.
|
10
|
+
|
11
|
+
*Joel Hawksley*
|
12
|
+
|
3
13
|
# 2.18.1
|
4
14
|
|
5
15
|
* Fix bug where previews didn't work when monkey patch was disabled.
|
data/README.md
CHANGED
@@ -47,6 +47,10 @@ Traditional Rails views have an implicit interface, making it hard to reason abo
|
|
47
47
|
|
48
48
|
ViewComponents use a standard Ruby initializer that clearly defines what is needed to render, making them easier (and safer) to reuse than partials.
|
49
49
|
|
50
|
+
#### Performance
|
51
|
+
|
52
|
+
Based on our [benchmarks](performance/benchmark.rb), ViewComponents are ~10x faster than partials.
|
53
|
+
|
50
54
|
#### Standards
|
51
55
|
|
52
56
|
Views often fail basic Ruby code quality standards: long methods, deep conditional nesting, and mystery guests abound.
|
@@ -164,19 +168,17 @@ Returning:
|
|
164
168
|
|
165
169
|
_Slots are currently under development as a successor to Content Areas. The Slot APIs should be considered unfinished and subject to breaking changes in non-major releases of ViewComponent._
|
166
170
|
|
167
|
-
Slots enable multiple blocks of content to be passed to a single ViewComponent.
|
168
|
-
|
169
|
-
Slots exist in two forms: normal slots and collection slots.
|
171
|
+
Slots enable multiple blocks of content to be passed to a single ViewComponent, reducing the need for sub-components (e.g. ModalHeader, ModalBody).
|
170
172
|
|
171
|
-
|
173
|
+
By default, slots can be rendered once per component. They provide an accessor with the name of the slot (`#header`) that returns an instance of `ViewComponent::Slot`, etc.
|
172
174
|
|
173
|
-
|
175
|
+
Slots declared with `collection: true` can be rendered multiple times. They provide an accessor with the pluralized name of the slot (`#rows`), which is an Array of `ViewComponent::Slot` instances.
|
174
176
|
|
175
|
-
To learn more about the design of the Slots API, see https://github.com/github/view_component/pull/348.
|
177
|
+
To learn more about the design of the Slots API, see https://github.com/github/view_component/pull/348 and https://github.com/github/view_component/discussions/325.
|
176
178
|
|
177
179
|
##### Defining Slots
|
178
180
|
|
179
|
-
Slots are defined by
|
181
|
+
Slots are defined by `with_slot`:
|
180
182
|
|
181
183
|
`with_slot :header`
|
182
184
|
|
@@ -184,11 +186,11 @@ To define a collection slot, add `collection: true`:
|
|
184
186
|
|
185
187
|
`with_slot :row, collection: true`
|
186
188
|
|
187
|
-
To define a slot with a custom class, pass `class_name`:
|
189
|
+
To define a slot with a custom Ruby class, pass `class_name`:
|
188
190
|
|
189
191
|
`with_slot :body, class_name: 'BodySlot`
|
190
192
|
|
191
|
-
Slot classes
|
193
|
+
_Note: Slot classes must be subclasses of `ViewComponent::Slot`._
|
192
194
|
|
193
195
|
##### Example ViewComponent with Slots
|
194
196
|
|
@@ -202,12 +204,12 @@ class BoxComponent < ViewComponent::Base
|
|
202
204
|
with_slot :row, collection: true, class_name: "Row"
|
203
205
|
|
204
206
|
class Header < ViewComponent::Slot
|
205
|
-
def initialize(
|
206
|
-
@
|
207
|
+
def initialize(classes: "")
|
208
|
+
@classes = classes
|
207
209
|
end
|
208
210
|
|
209
|
-
def
|
210
|
-
"Box-header #{@
|
211
|
+
def classes
|
212
|
+
"Box-header #{@classes}"
|
211
213
|
end
|
212
214
|
end
|
213
215
|
|
@@ -240,7 +242,7 @@ end
|
|
240
242
|
```erb
|
241
243
|
<div class="Box">
|
242
244
|
<% if header %>
|
243
|
-
<div class="<%= header.
|
245
|
+
<div class="<%= header.classes %>">
|
244
246
|
<%= header.content %>
|
245
247
|
</div>
|
246
248
|
<% end %>
|
@@ -260,7 +262,7 @@ end
|
|
260
262
|
<% end %>
|
261
263
|
<% if footer %>
|
262
264
|
<div class="Box-footer">
|
263
|
-
<%= footer %>
|
265
|
+
<%= footer.content %>
|
264
266
|
</div>
|
265
267
|
<% end %>
|
266
268
|
</div>
|
@@ -269,7 +271,7 @@ end
|
|
269
271
|
`# index.html.erb`
|
270
272
|
```erb
|
271
273
|
<%= render(BoxComponent.new) do |component| %>
|
272
|
-
<% component.slot(:header,
|
274
|
+
<% component.slot(:header, classes: "my-class-name") do %>
|
273
275
|
This is my header!
|
274
276
|
<% end %>
|
275
277
|
<% component.slot(:body) do %>
|
@@ -360,6 +362,32 @@ bin/rails generate component Example title content --sidecar
|
|
360
362
|
create app/components/example_component/example_component.html.erb
|
361
363
|
```
|
362
364
|
|
365
|
+
#### Component file inside Sidecar directory
|
366
|
+
|
367
|
+
It's also possible to place the Ruby component file inside the sidecar directory, grouping all related files in the same folder:
|
368
|
+
|
369
|
+
_Note: Avoid giving your containing folder the same name as your `.rb` file or there will be a conflict between Module and Class definitions_
|
370
|
+
|
371
|
+
```
|
372
|
+
app/components
|
373
|
+
├── ...
|
374
|
+
├── example
|
375
|
+
| ├── component.rb
|
376
|
+
| ├── component.css
|
377
|
+
| ├── component.html.erb
|
378
|
+
| └── component.js
|
379
|
+
├── ...
|
380
|
+
|
381
|
+
```
|
382
|
+
|
383
|
+
The component can then be rendered using the folder name as a namespace:
|
384
|
+
|
385
|
+
```erb
|
386
|
+
<%= render(Example::Component.new(title: "my title")) do %>
|
387
|
+
Hello, World!
|
388
|
+
<% end %>
|
389
|
+
```
|
390
|
+
|
363
391
|
### Conditional Rendering
|
364
392
|
|
365
393
|
Components can implement a `#render?` method to be called after initialization to determine if the component should render.
|
@@ -1003,6 +1031,11 @@ ViewComponent is built by:
|
|
1003
1031
|
|@johannesengl|@czj|@mrrooijen|@bradparker|@mattbrictson|
|
1004
1032
|
|Berlin, Germany|Paris, France|The Netherlands|Brisbane, Australia|San Francisco|
|
1005
1033
|
|
1034
|
+
|<img src="https://avatars.githubusercontent.com/mixergtz?s=256" alt="mixergtz" width="128" />|<img src="https://avatars.githubusercontent.com/jules2689?s=256" alt="jules2689" width="128" />|
|
1035
|
+
|:---:|:---:|
|
1036
|
+
|@mixergtz|@jules2689|
|
1037
|
+
|Medellin, Colombia|Toronto, Canada|
|
1038
|
+
|
1006
1039
|
## License
|
1007
1040
|
|
1008
1041
|
ViewComponent is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/view_component/base.rb
CHANGED
@@ -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,11 +110,13 @@ 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
|
|
@@ -381,17 +385,17 @@ module ViewComponent
|
|
381
385
|
|
382
386
|
location_without_extension = source_location.chomp(File.extname(source_location))
|
383
387
|
|
384
|
-
|
388
|
+
extensions = ActionView::Template.template_handler_extensions.join(",")
|
385
389
|
|
386
|
-
# view files in the same directory as
|
387
|
-
sidecar_files = Dir["#{location_without_extension}.*{#{
|
390
|
+
# view files in the same directory as the component
|
391
|
+
sidecar_files = Dir["#{location_without_extension}.*{#{extensions}}"]
|
388
392
|
|
389
393
|
# view files in a directory named like the component
|
390
394
|
directory = File.dirname(source_location)
|
391
395
|
filename = File.basename(source_location, ".rb")
|
392
396
|
component_name = name.demodulize.underscore
|
393
397
|
|
394
|
-
sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{
|
398
|
+
sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extensions}}"]
|
395
399
|
|
396
400
|
(sidecar_files - [source_location] + sidecar_directory_files)
|
397
401
|
end
|
@@ -44,21 +44,11 @@ module ViewComponent # :nodoc:
|
|
44
44
|
result.merge(layout: @layout)
|
45
45
|
end
|
46
46
|
|
47
|
-
# Returns the component object class associated to the preview.
|
48
|
-
def component
|
49
|
-
name.chomp("Preview").constantize
|
50
|
-
end
|
51
|
-
|
52
47
|
# Returns all of the available examples for the component preview.
|
53
48
|
def examples
|
54
49
|
public_instance_methods(false).map(&:to_s).sort
|
55
50
|
end
|
56
51
|
|
57
|
-
# Returns +true+ if the example of the component preview exists.
|
58
|
-
def example_exists?(example)
|
59
|
-
examples.include?(example)
|
60
|
-
end
|
61
|
-
|
62
52
|
# Returns +true+ if the preview exists.
|
63
53
|
def exists?(preview)
|
64
54
|
all.any? { |p| p.preview_name == preview }
|
@@ -104,10 +94,6 @@ module ViewComponent # :nodoc:
|
|
104
94
|
def preview_paths
|
105
95
|
Base.preview_paths
|
106
96
|
end
|
107
|
-
|
108
|
-
def show_previews
|
109
|
-
Base.show_previews
|
110
|
-
end
|
111
97
|
end
|
112
98
|
end
|
113
99
|
end
|
@@ -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
|
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.18.
|
4
|
+
version: 2.18.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-09 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,19 +171,19 @@ dependencies:
|
|
157
171
|
- !ruby/object:Gem::Version
|
158
172
|
version: 0.18.0
|
159
173
|
- !ruby/object:Gem::Dependency
|
160
|
-
name: simplecov-
|
174
|
+
name: simplecov-console
|
161
175
|
requirement: !ruby/object:Gem::Requirement
|
162
176
|
requirements:
|
163
177
|
- - "~>"
|
164
178
|
- !ruby/object:Gem::Version
|
165
|
-
version:
|
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:
|
186
|
+
version: 0.7.2
|
173
187
|
description:
|
174
188
|
email:
|
175
189
|
- opensource+view_component@github.com
|