actionview-component 1.14.1 → 1.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 204fb8e9a51fffd39203ff08885333086008e513a8855b36ddbe38a8e42b72ec
4
- data.tar.gz: e78a99c00889e3516552f4aa1c833be10704c32225ddcd78b713bfbae78d534c
3
+ metadata.gz: 38891bd3b2a3b00b7da81feb7e78fa55e5efbbf5f4bcf25abd47cf68893e7725
4
+ data.tar.gz: d53bc1d826b6504ea9b4fd4d5aa91362995fec79e12471c12466ea62a31c59b6
5
5
  SHA512:
6
- metadata.gz: 99efaec329aeb3b4ec886eb533ebf73ec28e33931ed65e9fba80111d0403d4703a82616ac1c40bdfdf0708ee8bb60aa5dcabc9218ca0aedd8c74fb60a2ca25a8
7
- data.tar.gz: 5b85c936cd7daacdf2ab71e96005444a22de2c6ff5af2d07ba412f2a6b28d5f4c828c2a9b92b84adb08816eef10492fa7a82c0c00299415a442b2f68cd7bb4da
6
+ metadata.gz: 3b3c2bfa37f043f19b52d9dcca5e07c8ecd7cdc3c4e06edaf775eedf5b1ced6e1a32bec284116a39222f2e67249928a175f72a75d33e84f81eb00cc918f40015
7
+ data.tar.gz: 626cf782c789aef2e982f13a2f8f313a3f9bf37e0bcaefc1010e9ee4f70335a6fc6062a48ca7e2d49ef4c9f0a8f4f3a9a1ed493fb5440d40da5253bf9393fb86
@@ -1,4 +1,4 @@
1
- <!-- See https://github.com/github/actionview-component/blob/master/CONTRIBUTING.md#submitting-a-pull-request -->
1
+ <!-- See https://github.com/github/view_component/blob/master/CONTRIBUTING.md#submitting-a-pull-request -->
2
2
 
3
3
  ### Summary
4
4
 
@@ -1,5 +1,29 @@
1
1
  # master
2
2
 
3
+ # v1.15.0
4
+
5
+ * Re-introduce ActionView::Component::TestHelpers.
6
+
7
+ *Joel Hawksley*
8
+
9
+ * Bypass monkey patch on Rails 6.1 builds.
10
+
11
+ *Joel Hawksley*
12
+
13
+ * Make `ActionView::Helpers::TagHelper` available in Previews.
14
+
15
+ ```ruby
16
+ def with_html_content
17
+ render(MyComponent.new) do
18
+ tag.div do
19
+ content_tag(:span, "Hello")
20
+ end
21
+ end
22
+ end
23
+ ```
24
+
25
+ *Sean Doyle*
26
+
3
27
  # v1.14.1
4
28
 
5
29
  * Fix bug where generator created invalid test code.
@@ -1,7 +1,7 @@
1
1
  # Contributing
2
2
 
3
- [fork]: https://github.com/github/actionview-component/fork
4
- [pr]: https://github.com/github/actionview-component/compare
3
+ [fork]: https://github.com/github/view_component/fork
4
+ [pr]: https://github.com/github/view_component/compare
5
5
  [style]: https://github.com/styleguide/ruby
6
6
  [code-of-conduct]: CODE_OF_CONDUCT.md
7
7
 
@@ -38,9 +38,9 @@ If you are the current maintainer of this gem:
38
38
  1. Add version heading/entries to `CHANGELOG.md`.
39
39
  1. Make sure your local dependencies are up to date: `bundle`
40
40
  1. Ensure that tests are green: `bundle exec rake`
41
- 1. Make a PR to github/actionview-component.
41
+ 1. Make a PR to github/view_component.
42
42
  1. Build a local gem: `gem build actionview-component.gemspec`
43
- 1. Merge github/actionview-component PR
43
+ 1. Merge github/view_component PR
44
44
  1. Tag and push: `git tag vx.xx.xx; git push --tags`
45
- 1. Create a GitHub release with the pushed tag (https://github.com/github/actionview-component/releases/new) and populate it with a list of the commits from `git log --pretty=format:"- %s" --reverse refs/tags/[OLD TAG]...refs/tags/[NEW TAG]`
45
+ 1. Create a GitHub release with the pushed tag (https://github.com/github/view_component/releases/new) and populate it with a list of the commits from `git log --pretty=format:"- %s" --reverse refs/tags/[OLD TAG]...refs/tags/[NEW TAG]`
46
46
  1. Push to rubygems.org -- `gem push actionview-component-VERSION.gem`
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- actionview-component (1.14.1)
4
+ actionview-component (1.15.0)
5
5
  capybara (>= 3)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # ViewComponent
2
2
  A view component framework for Rails.
3
3
 
4
- **Current Status**: Used in production at GitHub. Because of this, all changes will be thoroughly vetted, which could slow down the process of contributing. We will do our best to actively communicate status of pull requests with any contributors. If you have any substantial changes that you would like to make, it would be great to first [open an issue](http://github.com/github/actionview-component/issues/new) to discuss them with us.
4
+ **Current Status**: Used in production at GitHub. Because of this, all changes will be thoroughly vetted, which could slow down the process of contributing. We will do our best to actively communicate status of pull requests with any contributors. If you have any substantial changes that you would like to make, it would be great to first [open an issue](http://github.com/github/view_component/issues/new) to discuss them with us.
5
5
 
6
6
  ## Migration in progress
7
7
 
8
- This gem is in the process of a name / API change from `ActionView::Component` to `ViewComponent`, see https://github.com/github/actionview-component/issues/206.
8
+ This gem is in the process of a name / API change from `ActionView::Component` to `ViewComponent`, see https://github.com/github/view_component/issues/206.
9
9
 
10
10
  ### What's changing in the migration
11
11
 
@@ -19,7 +19,7 @@ This gem is in the process of a name / API change from `ActionView::Component` t
19
19
  1. Update components to inherit from `ViewComponent::Base`.
20
20
  1. Update component tests to inherit from `ViewComponent::TestCase`.
21
21
  1. Update component previews to inherit from `ViewComponent::Preview`.
22
- 1. Include `ViewComponent::TestHelpers` in your test suite.
22
+ 1. Include `ViewComponent::TestHelpers` in the appropriate test helper file.
23
23
 
24
24
  ## Roadmap
25
25
 
@@ -33,20 +33,16 @@ This library is designed to integrate as seamlessly as possible with Rails, with
33
33
 
34
34
  ## Compatibility
35
35
 
36
- `actionview-component` is tested for compatibility with combinations of Ruby `2.5`/`2.6`/`2.7` and Rails `5.0.0`/`5.2.3`/`6.0.0`/`6.1.0.alpha`.
36
+ `actionview-component` is tested for compatibility with combinations of Ruby `2.5`/`2.6`/`2.7` and Rails `5.0.0`/`5.2.3`/`6.0.0`/`master`.
37
37
 
38
38
  ## Installation
39
- Add this line to your application's Gemfile:
39
+
40
+ In `Gemfile`, add:
40
41
 
41
42
  ```ruby
42
43
  gem "actionview-component"
43
44
  ```
44
45
 
45
- And then execute:
46
- ```bash
47
- $ bundle
48
- ```
49
-
50
46
  In `config/application.rb`, add:
51
47
 
52
48
  ```bash
@@ -59,49 +55,41 @@ require "view_component/engine"
59
55
 
60
56
  `ViewComponent`s are Ruby classes that are used to render views. They take data as input and return output-safe HTML. Think of them as an evolution of the presenter/decorator/view model pattern, inspired by [React Components](https://reactjs.org/docs/react-component.html).
61
57
 
62
- ### Why components?
58
+ Components are most effective in cases where view code is reused or benefits from being tested directly.
63
59
 
64
- In working on views in the Rails monolith at GitHub (which has over 3700 templates), we have run into several key pain points:
60
+ ### Why should I use components?
65
61
 
66
62
  #### Testing
67
63
 
68
- Currently, Rails encourages testing views via integration or system tests. This discourages us from testing our views thoroughly, due to the costly overhead of exercising the routing/controller layer, instead of just the view. It also often leads to partials being tested for each view they are included in, cheapening the benefit of DRYing up our views.
64
+ Rails encourages testing views with integration tests. This discourages us from testing views thoroughly, due to the overhead of exercising the routing and controller layers in addition to the view.
69
65
 
70
- #### Code Coverage
66
+ For partials, this means being tested for each view they are included in, reducing the benefit of reusing them.
71
67
 
72
- Many common Ruby code coverage tools cannot properly handle coverage of views, making it difficult to audit how thorough our tests are and leading to gaps in our test suite.
68
+ `ViewComponent`s can be unit-tested. In the GitHub codebase, our component unit tests run in around 25 milliseconds, compared to about six seconds for integration tests.
73
69
 
74
70
  #### Data Flow
75
71
 
76
- Unlike a method declaration on an object, views do not declare the values they are expected to receive, making it hard to figure out what context is necessary to render them. This often leads to subtle bugs when we reuse a view across different contexts.
77
-
78
- #### Standards
72
+ Unlike a method declaration on an object, views do not declare the values they are expected to receive, making it hard to figure out what context is necessary to render them. This often leads to subtle bugs when reusing a view in different contexts.
79
73
 
80
- Our views often fail even the most basic standards of code quality we expect out of our Ruby classes: long methods, deep conditional nesting, and mystery guests abound.
74
+ By clearly defining the context necessary to render a `ViewComponent`, they're easier to reuse than partials.
81
75
 
82
- ### What are the benefits?
76
+ #### Standards
83
77
 
84
- #### Testing
78
+ Views often fail basic Ruby code quality standards: long methods, deep conditional nesting, and mystery guests abound.
85
79
 
86
- `ViewComponent` allows views to be unit-tested. In the main GitHub codebase, our unit tests run in around 25ms/test, vs. ~6s/test for integration tests.
80
+ `ViewComponent`s are Ruby objects, making it easy to follow code quality standards.
87
81
 
88
82
  #### Code Coverage
89
83
 
90
- `ViewComponent` is at least partially compatible with code coverage tools. We’ve seen some success with SimpleCov.
91
-
92
- #### Data flow
93
-
94
- By clearly defining the context necessary to render a component, we’ve found them to be easier to reuse than partials.
95
-
96
- ### When should I use components?
84
+ Many common Ruby code coverage tools cannot properly handle coverage of views, making it difficult to audit how thorough tests are and leading to missing coverage in test suites.
97
85
 
98
- Components are most effective in cases where view code is reused or needs to be tested directly.
86
+ `ViewComponent` is at least partially compatible with code coverage tools, such as SimpleCov.
99
87
 
100
88
  ### Building components
101
89
 
102
90
  #### Conventions
103
91
 
104
- Components are subclasses of `ViewComponent::Base` and live in `app/components`. You may wish to create an `ApplicationComponent` that is a subclass of `ViewComponent::Base` and inherit from that instead.
92
+ Components are subclasses of `ViewComponent::Base` and live in `app/components`. It's recommended to create an `ApplicationComponent` that is a subclass of `ViewComponent::Base` and inherit from that instead.
105
93
 
106
94
  Component class names end in -`Component`.
107
95
 
@@ -123,21 +111,17 @@ bin/rails generate component Example title content
123
111
  create app/components/example_component.html.erb
124
112
  ```
125
113
 
126
- `ViewComponent` includes template generators for the `erb`, `haml`, and `slim` template engines and will use the template engine specified in your Rails config (`config.generators.template_engine`) by default.
114
+ `ViewComponent` includes template generators for the `erb`, `haml`, and `slim` template engines and will use the template engine specified in the Rails configuration (`config.generators.template_engine`) by default.
127
115
 
128
- If you want to override this behavior, you can pass the template engine as an option to the generator:
116
+ The template engine can also be passed as an option to the generator:
129
117
 
130
118
  ```bash
131
119
  bin/rails generate component Example title content --template-engine slim
132
- invoke test_unit
133
- create test/components/example_component_test.rb
134
- create app/components/example_component.rb
135
- create app/components/example_component.html.slim
136
120
  ```
137
121
 
138
122
  #### Implementation
139
123
 
140
- A `ViewComponent` is a Ruby file and corresponding template file (in any format supported by Rails) with the same base name:
124
+ A `ViewComponent` is a Ruby file and corresponding template file with the same base name:
141
125
 
142
126
  `app/components/test_component.rb`:
143
127
  ```ruby
@@ -145,19 +129,15 @@ class TestComponent < ViewComponent::Base
145
129
  def initialize(title:)
146
130
  @title = title
147
131
  end
148
-
149
- private
150
-
151
- attr_reader :title
152
132
  end
153
133
  ```
154
134
 
155
135
  `app/components/test_component.html.erb`:
156
136
  ```erb
157
- <span title="<%= title %>"><%= content %></span>
137
+ <span title="<%= @title %>"><%= content %></span>
158
138
  ```
159
139
 
160
- We can render it in a view as:
140
+ Which is rendered in a view as:
161
141
 
162
142
  ```erb
163
143
  <%= render(TestComponent.new(title: "my title")) do %>
@@ -171,6 +151,8 @@ Which returns:
171
151
  <span title="my title">Hello, World!</span>
172
152
  ```
173
153
 
154
+ `ViewComponent` requires the presence of an `initialize` method in each component.
155
+
174
156
  #### Content Areas
175
157
 
176
158
  A component can declare additional content areas to be rendered in the component. For example:
@@ -180,11 +162,8 @@ A component can declare additional content areas to be rendered in the component
180
162
  class ModalComponent < ViewComponent::Base
181
163
  with_content_areas :header, :body
182
164
 
183
- def initialize(user:)
184
- @user = user
165
+ def initialize(*)
185
166
  end
186
-
187
- attr_reader :user
188
167
  end
189
168
  ```
190
169
 
@@ -196,12 +175,12 @@ end
196
175
  </div>
197
176
  ```
198
177
 
199
- We can render it in a view as:
178
+ Which is rendered in a view as:
200
179
 
201
180
  ```erb
202
- <%= render(ModalComponent.new(user: {name: 'Jane'})) do |component| %>
181
+ <%= render(ModalComponent.new) do |component| %>
203
182
  <% component.with(:header) do %>
204
- Hello <%= component.user[:name] %>
183
+ Hello Jane
205
184
  <% end %>
206
185
  <% component.with(:body) do %>
207
186
  <p>Have a great day.</p>
@@ -218,128 +197,14 @@ Which returns:
218
197
  </div>
219
198
  ```
220
199
 
221
- Content for content areas can be passed as arguments to the render method or as named blocks passed to the `with` method.
222
- This allows a few different combinations of ways to render the component:
223
-
224
- ##### Required render argument optionally overridden or wrapped by a named block
225
-
226
- `app/components/modal_component.rb`:
227
- ```ruby
228
- class ModalComponent < ViewComponent::Base
229
- with_content_areas :header, :body
230
-
231
- def initialize(header:)
232
- @header = header
233
- end
234
- end
235
- ```
236
-
237
- ```erb
238
- <%= render(ModalComponent.new(header: "Hi!")) do |component| %>
239
- <% component.with(:header) do %>
240
- <span class="help_icon"><%= component.header %></span>
241
- <% end %>
242
- <% component.with(:body) do %>
243
- <p>Have a great day.</p>
244
- <% end %>
245
- <% end %>
246
- ```
247
-
248
- ##### Required argument passed by render argument or by named block
249
-
250
- `app/components/modal_component.rb`:
251
- ```ruby
252
- class ModalComponent < ViewComponent::Base
253
- with_content_areas :header, :body
254
-
255
- def initialize(header: nil)
256
- @header = header
257
- end
258
- end
259
- ```
260
-
261
- `app/views/render_arg.html.erb`:
262
- ```erb
263
- <%= render(ModalComponent.new(header: "Hi!")) do |component| %>
264
- <% component.with(:body) do %>
265
- <p>Have a great day.</p>
266
- <% end %>
267
- <% end %>
268
- ```
269
-
270
- `app/views/with_block.html.erb`:
271
- ```erb
272
- <%= render(ModalComponent) do |component| %>
273
- <% component.with(:header) do %>
274
- <span class="help_icon">Hello</span>
275
- <% end %>
276
- <% component.with(:body) do %>
277
- <p>Have a great day.</p>
278
- <% end %>
279
- <% end %>
280
- ```
281
-
282
- ##### Optional argument passed by render argument, by named block, or neither
283
-
284
- `app/components/modal_component.rb`:
285
- ```ruby
286
- class ModalComponent < ViewComponent::Base
287
- with_content_areas :header, :body
288
-
289
- def initialize(header: nil)
290
- @header = header
291
- end
292
- end
293
- ```
294
-
295
- `app/components/modal_component.html.erb`:
296
- ```erb
297
- <div class="modal">
298
- <% if header %>
299
- <div class="header"><%= header %></div>
300
- <% end %>
301
- <div class="body"><%= body %></div>
302
- </div>
303
- ```
304
-
305
- `app/views/render_arg.html.erb`:
306
- ```erb
307
- <%= render(ModalComponent.new(header: "Hi!")) do |component| %>
308
- <% component.with(:body) do %>
309
- <p>Have a great day.</p>
310
- <% end %>
311
- <% end %>
312
- ```
313
-
314
- `app/views/with_block.html.erb`:
315
- ```erb
316
- <%= render(ModalComponent.new) do |component| %>
317
- <% component.with(:header) do %>
318
- <span class="help_icon">Hello</span>
319
- <% end %>
320
- <% component.with(:body) do %>
321
- <p>Have a great day.</p>
322
- <% end %>
323
- <% end %>
324
- ```
325
-
326
- `app/views/no_header.html.erb`:
327
- ```erb
328
- <%= render(ModalComponent.new) do |component| %>
329
- <% component.with(:body) do %>
330
- <p>Have a great day.</p>
331
- <% end %>
332
- <% end %>
333
- ```
334
-
335
200
  ### Conditional Rendering
336
201
 
337
- Components can implement a `#render?` method which indicates if they should be rendered, or not at all.
202
+ Components can implement a `#render?` method to determine if they should be rendered.
338
203
 
339
- For example, you might have a component that displays a "Please confirm your email address" banner to users who haven't confirmed their email address. The logic for rendering the banner would need to go in either the component template:
204
+ For example, given a component that displays a banner to users who haven't confirmed their email address, the logic for whether to render the banner would need to go in either the component template:
340
205
 
206
+ `app/components/confirm_email_component.html.erb`
341
207
  ```
342
- <!-- app/components/confirm_email_component.html.erb -->
343
208
  <% if user.requires_confirmation? %>
344
209
  <div class="alert">
345
210
  Please confirm your email address.
@@ -349,17 +214,17 @@ For example, you might have a component that displays a "Please confirm your ema
349
214
 
350
215
  or the view that renders the component:
351
216
 
217
+ `app/views/_banners.html.erb`
352
218
  ```erb
353
- <!-- app/views/_banners.html.erb -->
354
219
  <% if current_user.requires_confirmation? %>
355
220
  <%= render(ConfirmEmailComponent.new(user: current_user)) %>
356
221
  <% end %>
357
222
  ```
358
223
 
359
- The `#render?` hook allows you to move this logic into the Ruby class, leaving your views more readable and declarative in style:
224
+ Instead, the `#render?` hook expresses this logic in the Ruby class, simplifying the view:
360
225
 
226
+ `app/components/confirm_email_component.rb`
361
227
  ```ruby
362
- # app/components/confirm_email_component.rb
363
228
  class ConfirmEmailComponent < ViewComponent::Base
364
229
  def initialize(user:)
365
230
  @user = user
@@ -368,26 +233,24 @@ class ConfirmEmailComponent < ViewComponent::Base
368
233
  def render?
369
234
  @user.requires_confirmation?
370
235
  end
371
-
372
- attr_reader :user
373
236
  end
374
237
  ```
375
238
 
239
+ `app/components/confirm_email_component.html.erb`
376
240
  ```
377
- <!-- app/components/confirm_email_component.html.erb -->
378
241
  <div class="banner">
379
242
  Please confirm your email address.
380
243
  </div>
381
244
  ```
382
245
 
246
+ `app/views/_banners.html.erb`
383
247
  ```erb
384
- <!-- app/views/_banners.html.erb -->
385
248
  <%= render(ConfirmEmailComponent.new(user: current_user)) %>
386
249
  ```
387
250
 
388
251
  ### Testing
389
252
 
390
- Components are unit tested directly. The `render_inline` test helper is compatible with Capybara matchers, allowing us to test the component above as:
253
+ Unit test components directly, using the `render_inline` test helper and Capybara matchers:
391
254
 
392
255
  ```ruby
393
256
  require "view_component/test_case"
@@ -401,11 +264,9 @@ class MyComponentTest < ViewComponent::TestCase
401
264
  end
402
265
  ```
403
266
 
404
- In general, we’ve found it makes the most sense to test components based on their rendered HTML.
405
-
406
267
  #### Action Pack Variants
407
268
 
408
- To test a specific variant you can wrap your test with the `with_variant` helper method as:
269
+ Use the `with_variant` helper to test specific variants:
409
270
 
410
271
  ```ruby
411
272
  test "render component for tablet" do
@@ -418,14 +279,10 @@ end
418
279
  ```
419
280
 
420
281
  ### Previewing Components
421
- `ViewComponent::Preview` provides a way to see how components look by visiting a special URL that renders them.
422
- In the previous example, the preview class for `TestComponent` would be called `TestComponentPreview` and located in `test/components/previews/test_component_preview.rb`.
423
- To see the preview of the component with a given title, implement a method that renders the component.
424
- You can define as many examples as you want:
282
+ `ViewComponent::Preview`, like `ActionMailer::Preview`, provides a way to preview components in isolation:
425
283
 
284
+ `test/components/previews/test_component_preview.rb`
426
285
  ```ruby
427
- # test/components/previews/test_component_preview.rb
428
-
429
286
  class TestComponentPreview < ViewComponent::Preview
430
287
  def with_default_title
431
288
  render(TestComponent.new(title: "Test component default"))
@@ -434,17 +291,33 @@ class TestComponentPreview < ViewComponent::Preview
434
291
  def with_long_title
435
292
  render(TestComponent.new(title: "This is a really long title to see how the component renders this"))
436
293
  end
294
+
295
+ def with_content_block
296
+ render(TestComponent.new(title: "This component accepts a block of content") do
297
+ tag.div do
298
+ content_tag(:span, "Hello")
299
+ end
300
+ end
301
+ end
437
302
  end
438
303
  ```
439
304
 
440
- The previews will be available in <http://localhost:3000/rails/components/test_component/with_default_title>
441
- and <http://localhost:3000/rails/components/test_component/with_long_title>.
305
+ Which generates <http://localhost:3000/rails/components/test_component/with_default_title>,
306
+ <http://localhost:3000/rails/components/test_component/with_long_title>,
307
+ and <http://localhost:3000/rails/components/test_component/with_content_block>.
442
308
 
443
- Previews use the application layout by default, but you can also use other layouts from your app:
309
+ The `ViewComponent::Preview` base class includes
310
+ [`ActionView::Helpers::TagHelper`][tag-helper], which provides the [`tag`][tag]
311
+ and [`content_tag`][content_tag] view helper methods.
444
312
 
445
- ```ruby
446
- # test/components/previews/test_component_preview.rb
313
+ [tag-helper]: https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html
314
+ [tag]: https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-tag
315
+ [content_tag]: https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag
447
316
 
317
+ Previews default to the application layout, but can be overridden:
318
+
319
+ `test/components/previews/test_component_preview.rb`
320
+ ```ruby
448
321
  class TestComponentPreview < ViewComponent::Preview
449
322
  layout "admin"
450
323
 
@@ -452,52 +325,46 @@ class TestComponentPreview < ViewComponent::Preview
452
325
  end
453
326
  ```
454
327
 
455
- By default, the preview classes live in `test/components/previews`.
456
- This can be configured using the `preview_path` option.
457
- For example, if you want to use `lib/component_previews`, set the following in `config/application.rb`:
328
+ Preview classes live in `test/components/previews`, can be configured using the `preview_path` option.
458
329
 
330
+ To use `lib/component_previews`:
331
+
332
+ `config/application.rb`
459
333
  ```ruby
460
334
  config.action_view_component.preview_path = "#{Rails.root}/lib/component_previews"
461
335
  ```
462
336
 
463
337
  #### Configuring TestController
464
338
 
465
- By default components tests and previews expect your Rails project to contain an `ApplicationController` class from which Controller classes inherit.
466
- This can be configured using the `test_controller` option.
467
- For example, if your controllers inherit from `BaseController`, set the following in `config/application.rb`:
339
+ Component tests and previews assume the existence of an `ApplicationController` class, be can beconfigured using the `test_controller` option:
468
340
 
341
+ `config/application.rb`
469
342
  ```ruby
470
343
  config.action_view_component.test_controller = "BaseController"
471
344
  ```
472
345
 
473
346
  ### Setting up RSpec
474
347
 
475
- If you're using RSpec, you can configure component specs to have access to test helpers. Add the following to
476
- `spec/rails_helper.rb`:
348
+ To use RSpec, add the following:
477
349
 
350
+ `spec/rails_helper.rb`
478
351
  ```ruby
479
352
  require "view_component/test_helpers"
480
353
 
481
354
  RSpec.configure do |config|
482
- # ...
483
-
484
- # Ensure that the test helpers are available in component specs
485
- config.include ViewComponent::TestHelpers, type: :component
355
+ config.include ViewComponent::TestHelpers, type: :component
486
356
  end
487
357
  ```
488
358
 
489
- Specs created by the generator should now have access to test helpers like `render_inline`.
359
+ Specs created by the generator have access to test helpers like `render_inline`.
490
360
 
491
- To use component previews, set the following in `config/application.rb`:
361
+ To use component previews:
492
362
 
363
+ `config/application.rb`
493
364
  ```ruby
494
365
  config.action_view_component.preview_path = "#{Rails.root}/spec/components/previews"
495
366
  ```
496
367
 
497
- ### Initializer requirement
498
-
499
- `ViewComponent` requires the presence of an `initialize` method in each component.
500
-
501
368
  ## Frequently Asked Questions
502
369
 
503
370
  ### Can I use other templating languages besides ERB?
@@ -523,11 +390,11 @@ Inline templates have been removed (for now) due to concerns raised by [@soutaro
523
390
  - [Introducing ActionView::Component with Joel Hawksley, Ruby on Rails Podcast](http://5by5.tv/rubyonrails/276)
524
391
  - [Rails to Introduce View Components, Dev.to](https://dev.to/andy/rails-to-introduce-view-components-3ome)
525
392
  - [ActionView::Components in Rails 6.1, Drifting Ruby](https://www.driftingruby.com/episodes/actionview-components-in-rails-6-1)
526
- - [Demo repository, actionview-component-demo](https://github.com/joelhawksley/actionview-component-demo)
393
+ - [Demo repository, view-component-demo](https://github.com/joelhawksley/view-component-demo)
527
394
 
528
395
  ## Contributing
529
396
 
530
- Bug reports and pull requests are welcome on GitHub at https://github.com/github/actionview-component. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./CONTRIBUTING.md) as well.
397
+ Bug reports and pull requests are welcome on GitHub at https://github.com/github/view_component. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./CONTRIBUTING.md) as well.
531
398
 
532
399
  ## Contributors
533
400
 
@@ -563,6 +430,11 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/github
563
430
  |@blakewilliams|
564
431
  |Boston, MA|
565
432
 
433
+ |<img src="https://avatars.githubusercontent.com/seanpdoyle?s=256" alt="seanpdoyle" width="128" />|
434
+ |:---:|
435
+ |@seanpdoyle|
436
+ |New York, NY|
437
+
566
438
  ## License
567
439
 
568
440
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -9,11 +9,11 @@ Gem::Specification.new do |spec|
9
9
  spec.name = "actionview-component"
10
10
  spec.version = ViewComponent::VERSION::STRING
11
11
  spec.authors = ["GitHub Open Source"]
12
- spec.email = ["opensource+actionview-component@github.com"]
12
+ spec.email = ["opensource+view_component@github.com"]
13
13
 
14
14
  spec.summary = %q{View components for Rails}
15
- spec.description = %q{View components for Rails, intended for upstreaming in Rails 6.1}
16
- spec.homepage = "https://github.com/github/actionview-component"
15
+ spec.description = %q{View components for Rails}
16
+ spec.homepage = "https://github.com/github/view_component"
17
17
  spec.license = "MIT"
18
18
 
19
19
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
@@ -0,0 +1,76 @@
1
+ Name: Dave Paola
2
+
3
+ Github Handle: [@dpaola2](https://github.com/dpaola2)
4
+
5
+ [Jellyswitch](https://www.jellyswitch.com) is a coworking space management platform
6
+
7
+ In response to [this tweet](https://twitter.com/joelhawksley/status/1232674647327547394):
8
+
9
+ I recently began refactoring many of my partials into components. Along the way I discovered an interesting use case, which was to componentize the various bootstrap components I was already using.
10
+
11
+ Some examples:
12
+
13
+ - I've componentized the specific layout that I've designed using the grid system. I have defined a `FullWidthLayout` component that wraps its contents in the correct classes to give my layout a good design on both mobile and desktop. (On desktop, there is a sidebar, and on mobile, the sidebar floats on top in a collapsed fashion.)
14
+ - [Modals](https://getbootstrap.com/docs/4.4/components/modal/) are now componentized and accept arguments. I had them as partials before, but having ruby classes is an upgrade.
15
+ - [Breadcrumbs](https://getbootstrap.com/docs/4.4/components/breadcrumb/) same as above.
16
+
17
+ Here's one that I use a LOT: `OnOffSwitch`:
18
+
19
+ ```ruby
20
+ class OnOffSwitch < ApplicationComponent
21
+ def initialize(predicate:, path:, disabled: false, label: nil)
22
+ @predicate = predicate
23
+ @path = path
24
+ @disabled = disabled
25
+ @label = label
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :predicate, :path, :disabled, :label
31
+
32
+ def icon_class
33
+ if predicate
34
+ "fas fa-toggle-on"
35
+ else
36
+ "fas fa-toggle-off"
37
+ end
38
+ end
39
+ end
40
+ ```
41
+
42
+ ```erb
43
+ <div class="d-flex align-items-center">
44
+ <% if !disabled %>
45
+ <%= link_to path, class: "text-body", remote: true do %>
46
+ <span style="font-size: 20pt">
47
+ <% if predicate %>
48
+ <span class="text-success">
49
+ <i class="<%= icon_class %>"></i>
50
+ </span>
51
+ <% else %>
52
+ <span class="text-danger">
53
+ <i class="<%= icon_class %>"></i>
54
+ </span>
55
+ <% end %>
56
+ </span>
57
+ <% end %>
58
+ <% else %>
59
+ <span style="font-size: 20pt">
60
+ <span class="text-muted">
61
+ <i class="<%= icon_class %>"></i>
62
+ </span>
63
+ </span>
64
+ <% end %>
65
+ &nbsp;
66
+ <%= content %>
67
+ </div>
68
+ ```
69
+
70
+ Here is an example of how this looks:
71
+
72
+ <img width="653" alt="Screenshot 2020-02-26 08 34 07" src="https://user-images.githubusercontent.com/150509/75365920-cbfb9500-5872-11ea-8234-f1343629a462.png">
73
+
74
+ I have found that refactoring complex views is made easier and faster by first putting them into a component, extracting the conditionals and other logic into private methods and proceeding from there. And I wind up with a very nice set of well-factored components and sub-components, with argument lists and validations and so on. I think the rails community is really going to benefit from this library, and I'm hugely appreciative of y'all's efforts on it!
75
+
76
+ I plan to release an early version of the bootstrap components we've developed at some point in the near future. I would love to collaborate and learn the most appropriate way to structure that contribution.
@@ -2,7 +2,8 @@
2
2
 
3
3
  module ActionView
4
4
  module Component
5
- class TestCase < ViewComponent::TestCase
5
+ class TestCase
6
+ include ActionView::Component::TestHelpers
6
7
  end
7
8
  end
8
9
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Component
5
+ module TestHelpers
6
+ include ViewComponent::TestHelpers
7
+
8
+ def render_component(component, **args, &block)
9
+ ActiveSupport::Deprecation.warn(
10
+ "`render_component` has been deprecated in favor of `render_inline`, and will be removed in v2.0.0."
11
+ )
12
+
13
+ render_inline(component, args, &block)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -23,6 +23,7 @@ module ActionView
23
23
  autoload :Base
24
24
  autoload :Preview
25
25
  autoload :TestCase
26
+ autoload :TestHelpers
26
27
  end
27
28
  end
28
29
 
@@ -4,6 +4,7 @@ require "active_support/descendants_tracker"
4
4
 
5
5
  module ViewComponent # :nodoc:
6
6
  class Preview
7
+ include ActionView::Helpers::TagHelper
7
8
  extend ActiveSupport::DescendantsTracker
8
9
 
9
10
  def render(component, **args, &block)
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module RenderMonkeyPatch # :nodoc:
5
5
  def render(options = {}, args = {}, &block)
6
- if options.respond_to?(:render_in)
6
+ if options.respond_to?(:render_in) && Rails.version.to_f < 6.1
7
7
  options.render_in(self, &block)
8
8
  elsif options.is_a?(Class) && options < ActionView::Component::Base
9
9
  ActiveSupport::Deprecation.warn(
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module RenderingMonkeyPatch # :nodoc:
5
5
  def render(options = {}, args = {})
6
- if options.respond_to?(:render_in)
6
+ if options.respond_to?(:render_in) && Rails.version.to_f < 6.1
7
7
  self.response_body = options.render_in(self.view_context)
8
8
  else
9
9
  super
@@ -24,14 +24,6 @@ module ViewComponent
24
24
  @request ||= ActionDispatch::TestRequest.create
25
25
  end
26
26
 
27
- def render_component(component, **args, &block)
28
- ActiveSupport::Deprecation.warn(
29
- "`render_component` has been deprecated in favor of `render_inline`, and will be removed in v2.0.0."
30
- )
31
-
32
- render_inline(component, args, &block)
33
- end
34
-
35
27
  def with_variant(variant)
36
28
  old_variants = controller.view_context.lookup_context.variants
37
29
 
@@ -3,8 +3,8 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 14
7
- PATCH = 1
6
+ MINOR = 15
7
+ PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
10
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview-component
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.1
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-03 00:00:00.000000000 Z
11
+ date: 2020-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -136,9 +136,9 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: 0.13.0
139
- description: View components for Rails, intended for upstreaming in Rails 6.1
139
+ description: View components for Rails
140
140
  email:
141
- - opensource+actionview-component@github.com
141
+ - opensource+view_component@github.com
142
142
  executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
@@ -158,11 +158,13 @@ files:
158
158
  - Rakefile
159
159
  - actionview-component.gemspec
160
160
  - app/controllers/rails/components_controller.rb
161
+ - docs/case-studies/jellyswitch.md
161
162
  - lib/action_view/component.rb
162
163
  - lib/action_view/component/base.rb
163
164
  - lib/action_view/component/preview.rb
164
165
  - lib/action_view/component/railtie.rb
165
166
  - lib/action_view/component/test_case.rb
167
+ - lib/action_view/component/test_helpers.rb
166
168
  - lib/rails/generators/component/USAGE
167
169
  - lib/rails/generators/component/component_generator.rb
168
170
  - lib/rails/generators/component/templates/component.rb.tt
@@ -197,7 +199,7 @@ files:
197
199
  - script/install
198
200
  - script/release
199
201
  - script/test
200
- homepage: https://github.com/github/actionview-component
202
+ homepage: https://github.com/github/view_component
201
203
  licenses:
202
204
  - MIT
203
205
  metadata: