actionview-component 1.11.1 → 1.12.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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE +2 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +3 -3
- data/README.md +17 -22
- data/{lib/railties/lib → app/controllers}/rails/components_controller.rb +10 -4
- data/lib/action_view/component.rb +1 -1
- data/lib/action_view/component/base.rb +20 -21
- data/lib/action_view/component/engine.rb +63 -0
- data/lib/action_view/component/railtie.rb +1 -63
- data/lib/action_view/component/version.rb +2 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfaa667b7c02706e492cb8f92221bcc2ec39137b525faccdaadbef76435c9880
|
4
|
+
data.tar.gz: b9bf382421e68d742e5427b67b5b84163cbca8c47fca9e6789391ceea4bc5f2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8563f9ef8e370a5a0dfdc15813e72b2dd35c6f0b37de6fa81ba84a50b20427049d0e00fc5ecbb72ff4f15bb50e0793e5afcaf59ac85d3d5b78e4091b7080ca79
|
7
|
+
data.tar.gz: 5447df2d42fddbb35b90d05e328e3de3c78d7db2a44d92a29de49986630b9dbc2203012bc9fdc48812422b8a761e881f0d106e0d8abb55ed412b07687c00d0dd
|
data/.github/ISSUE_TEMPLATE
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# master
|
2
|
+
|
3
|
+
# v1.12.0
|
4
|
+
|
5
|
+
* Revert: Remove initializer requirement for Ruby 2.7+
|
6
|
+
|
7
|
+
*Joel Hawksley*
|
8
|
+
|
9
|
+
* Restructure Railtie into Engine
|
10
|
+
|
11
|
+
*Sean Doyle*
|
12
|
+
|
13
|
+
* Allow components to override before_render_check
|
14
|
+
|
15
|
+
*Joel Hawksley*
|
16
|
+
|
1
17
|
# v1.11.1
|
2
18
|
|
3
19
|
* Relax Capybara requirement.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
actionview-component (1.
|
4
|
+
actionview-component (1.12.0)
|
5
5
|
capybara (>= 3)
|
6
6
|
|
7
7
|
GEM
|
@@ -107,7 +107,7 @@ GEM
|
|
107
107
|
mini_portile2 (2.4.0)
|
108
108
|
minitest (5.1.0)
|
109
109
|
nio4r (2.5.2)
|
110
|
-
nokogiri (1.10.
|
110
|
+
nokogiri (1.10.8)
|
111
111
|
mini_portile2 (~> 2.4.0)
|
112
112
|
parallel (1.17.0)
|
113
113
|
parser (2.6.3.0)
|
@@ -144,7 +144,7 @@ GEM
|
|
144
144
|
thor (>= 0.20.3, < 2.0)
|
145
145
|
rainbow (3.0.0)
|
146
146
|
rake (10.5.0)
|
147
|
-
regexp_parser (1.
|
147
|
+
regexp_parser (1.7.0)
|
148
148
|
rubocop (0.74.0)
|
149
149
|
jaro_winkler (~> 1.5.1)
|
150
150
|
parallel (~> 1.10)
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
_Note: This gem is in the process of a name / API change, see https://github.com/github/actionview-component/issues/206_
|
2
2
|
|
3
|
+
_You are viewing the README for the development version of ActionView::Component. If you are using the current release version you can find the README at https://github.com/github/actionview-component/blob/v1.11.1/README.md_
|
4
|
+
|
3
5
|
# ActionView::Component
|
4
6
|
`ActionView::Component` is a framework for building view components in Rails.
|
5
7
|
|
@@ -7,13 +9,13 @@ _Note: This gem is in the process of a name / API change, see https://github.com
|
|
7
9
|
|
8
10
|
## Roadmap
|
9
11
|
|
10
|
-
|
12
|
+
Support for third-party component frameworks was merged into Rails `6.1.0.alpha` in https://github.com/rails/rails/pull/36388 and https://github.com/rails/rails/pull/37919. Our goal with this project is to provide a first-class component framework for this new capability in Rails.
|
11
13
|
|
12
|
-
|
14
|
+
This gem includes a backport of those changes for Rails `5.0.0` through `6.1.0.alpha`.
|
13
15
|
|
14
16
|
## Design philosophy
|
15
17
|
|
16
|
-
|
18
|
+
This library is designed to integrate as seamlessly as possible with Rails, with the [least surprise](https://www.artima.com/intv/ruby4.html).
|
17
19
|
|
18
20
|
## Compatibility
|
19
21
|
|
@@ -77,24 +79,14 @@ Our views often fail even the most basic standards of code quality we expect out
|
|
77
79
|
|
78
80
|
By clearly defining the context necessary to render a component, we’ve found them to be easier to reuse than partials.
|
79
81
|
|
80
|
-
#### Performance
|
81
|
-
|
82
|
-
In early benchmarks, we’ve seen performance improvements over the existing rendering pipeline. For a test page with nested renders 10 levels deep, we’re seeing around a 5x increase in speed over partials:
|
83
|
-
|
84
|
-
```
|
85
|
-
Comparison:
|
86
|
-
component: 6515.4 i/s
|
87
|
-
partial: 1251.2 i/s - 5.21x slower
|
88
|
-
```
|
89
|
-
|
90
|
-
_Rails 6.1.0.alpha, [joelhawksley/actionview-component-demo](https://github.com/joelhawksley/actionview-component-demo), /benchmark route, via `RAILS_ENV=production rails s`, measured with [evanphx/benchmark-ips](https://github.com/evanphx/benchmark-ips)_
|
91
|
-
|
92
82
|
### When should I use components?
|
93
83
|
|
94
84
|
Components are most effective in cases where view code is reused or needs to be tested directly.
|
95
85
|
|
96
86
|
### Building components
|
97
87
|
|
88
|
+
#### Conventions
|
89
|
+
|
98
90
|
Components are subclasses of `ActionView::Component::Base` and live in `app/components`. You may wish to create an `ApplicationComponent` that is a subclass of `ActionView::Component::Base` and inherit from that instead.
|
99
91
|
|
100
92
|
Component class names end in -`Component`.
|
@@ -197,6 +189,8 @@ class ModalComponent < ActionView::Component::Base
|
|
197
189
|
def initialize(user:)
|
198
190
|
@user = user
|
199
191
|
end
|
192
|
+
|
193
|
+
attr_reader :user
|
200
194
|
end
|
201
195
|
```
|
202
196
|
|
@@ -204,7 +198,7 @@ end
|
|
204
198
|
```erb
|
205
199
|
<div class="modal">
|
206
200
|
<div class="header"><%= header %></div>
|
207
|
-
<div class="body"><%= body
|
201
|
+
<div class="body"><%= body %></div>
|
208
202
|
</div>
|
209
203
|
```
|
210
204
|
|
@@ -213,7 +207,7 @@ We can render it in a view as:
|
|
213
207
|
```erb
|
214
208
|
<%= render(ModalComponent.new(user: {name: 'Jane'})) do |component| %>
|
215
209
|
<% component.with(:header) do %>
|
216
|
-
Hello <%= user[:name] %>
|
210
|
+
Hello <%= component.user[:name] %>
|
217
211
|
<% end %>
|
218
212
|
<% component.with(:body) do %>
|
219
213
|
<p>Have a great day.</p>
|
@@ -250,7 +244,7 @@ end
|
|
250
244
|
|
251
245
|
```erb
|
252
246
|
<%= render(ModalComponent.new(header: "Hi!")) do |component| %>
|
253
|
-
<%
|
247
|
+
<% component.with(:header) do %>
|
254
248
|
<span class="help_icon"><%= component.header %></span>
|
255
249
|
<% end %>
|
256
250
|
<% component.with(:body) do %>
|
@@ -316,7 +310,7 @@ end
|
|
316
310
|
<% if header %>
|
317
311
|
<div class="header"><%= header %></div>
|
318
312
|
<% end %>
|
319
|
-
<div class="body"><%= body
|
313
|
+
<div class="body"><%= body %></div>
|
320
314
|
</div>
|
321
315
|
```
|
322
316
|
|
@@ -378,7 +372,7 @@ The `#render?` hook allows you to move this logic into the Ruby class, leaving y
|
|
378
372
|
|
379
373
|
```ruby
|
380
374
|
# app/components/confirm_email_component.rb
|
381
|
-
class ConfirmEmailComponent <
|
375
|
+
class ConfirmEmailComponent < ActionView::Component::Base
|
382
376
|
def initialize(user:)
|
383
377
|
@user = user
|
384
378
|
end
|
@@ -386,6 +380,8 @@ class ConfirmEmailComponent < ApplicationComponent
|
|
386
380
|
def render?
|
387
381
|
@user.requires_confirmation?
|
388
382
|
end
|
383
|
+
|
384
|
+
attr_reader :user
|
389
385
|
end
|
390
386
|
```
|
391
387
|
|
@@ -512,8 +508,7 @@ config.action_view_component.preview_path = "#{Rails.root}/spec/components/previ
|
|
512
508
|
|
513
509
|
### Initializer requirement
|
514
510
|
|
515
|
-
|
516
|
-
However, `initialize` is no longer required for projects using 2.7.x and above.
|
511
|
+
ActionView::Component requires the presence of an `initialize` method in each component.
|
517
512
|
|
518
513
|
## Frequently Asked Questions
|
519
514
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "rails/application_controller"
|
4
4
|
|
5
5
|
class Rails::ComponentsController < Rails::ApplicationController # :nodoc:
|
6
|
-
prepend_view_path File.expand_path("templates/rails", __dir__)
|
6
|
+
prepend_view_path File.expand_path("../../../lib/railties/lib/rails/templates/rails", __dir__)
|
7
7
|
prepend_view_path "#{Rails.root}/app/views/" if defined?(Rails.root)
|
8
8
|
|
9
9
|
around_action :set_locale, only: :previews
|
@@ -17,19 +17,25 @@ class Rails::ComponentsController < Rails::ApplicationController # :nodoc:
|
|
17
17
|
def index
|
18
18
|
@previews = ActionView::Component::Preview.all
|
19
19
|
@page_title = "Component Previews"
|
20
|
-
|
20
|
+
# rubocop:disable GitHub/RailsControllerRenderPathsExist
|
21
|
+
render "components/index"
|
22
|
+
# rubocop:enable GitHub/RailsControllerRenderPathsExist
|
21
23
|
end
|
22
24
|
|
23
25
|
def previews
|
24
26
|
if params[:path] == @preview.preview_name
|
25
27
|
@page_title = "Component Previews for #{@preview.preview_name}"
|
26
|
-
|
28
|
+
# rubocop:disable GitHub/RailsControllerRenderPathsExist
|
29
|
+
render "components/previews"
|
30
|
+
# rubocop:enable GitHub/RailsControllerRenderPathsExist
|
27
31
|
else
|
28
32
|
@example_name = File.basename(params[:path])
|
29
33
|
@render_args = @preview.render_args(@example_name)
|
30
34
|
layout = @render_args[:layout]
|
31
35
|
opts = layout.nil? ? {} : { layout: layout }
|
32
|
-
|
36
|
+
# rubocop:disable GitHub/RailsControllerRenderPathsExist
|
37
|
+
render "components/preview", **opts
|
38
|
+
# rubocop:enable GitHub/RailsControllerRenderPathsExist
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
@@ -14,10 +14,9 @@ module ActionView
|
|
14
14
|
class_attribute :content_areas, default: []
|
15
15
|
self.content_areas = [] # default doesn't work until Rails 5.2
|
16
16
|
|
17
|
-
# Entrypoint for rendering components.
|
17
|
+
# Entrypoint for rendering components.
|
18
18
|
#
|
19
19
|
# view_context: ActionView context from calling view
|
20
|
-
# args(hash): params to be passed to component being rendered
|
21
20
|
# block: optional block to be captured within the view context
|
22
21
|
#
|
23
22
|
# returns HTML that has been escaped by the respective template handler
|
@@ -35,11 +34,11 @@ module ActionView
|
|
35
34
|
# <span title="<%= @title %>">Hello, <%= content %>!</span>
|
36
35
|
#
|
37
36
|
# In use:
|
38
|
-
# <%= render MyComponent
|
37
|
+
# <%= render MyComponent.new(title: "greeting") do %>world<% end %>
|
39
38
|
# returns:
|
40
39
|
# <span title="greeting">Hello, world!</span>
|
41
40
|
#
|
42
|
-
def render_in(view_context,
|
41
|
+
def render_in(view_context, &block)
|
43
42
|
self.class.compile!
|
44
43
|
@view_context = view_context
|
45
44
|
@view_renderer ||= view_context.view_renderer
|
@@ -53,15 +52,21 @@ module ActionView
|
|
53
52
|
|
54
53
|
@content = view_context.capture(self, &block) if block_given?
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
return "" unless render?
|
55
|
+
before_render_check
|
59
56
|
|
60
|
-
|
57
|
+
if render?
|
58
|
+
send(self.class.call_method_name(@variant))
|
59
|
+
else
|
60
|
+
""
|
61
|
+
end
|
61
62
|
ensure
|
62
63
|
@current_template = old_current_template
|
63
64
|
end
|
64
65
|
|
66
|
+
def before_render_check
|
67
|
+
validate!
|
68
|
+
end
|
69
|
+
|
65
70
|
def render?
|
66
71
|
true
|
67
72
|
end
|
@@ -142,14 +147,12 @@ module ActionView
|
|
142
147
|
|
143
148
|
def source_location
|
144
149
|
@source_location ||=
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
initialize_method.source_location[0] if initialize_method.owner == self
|
152
|
-
end
|
150
|
+
begin
|
151
|
+
# Require `#initialize` to be defined so that we can use `method#source_location`
|
152
|
+
# to look up the filename of the component.
|
153
|
+
initialize_method = instance_method(:initialize)
|
154
|
+
initialize_method.source_location[0] if initialize_method.owner == self
|
155
|
+
end
|
153
156
|
end
|
154
157
|
|
155
158
|
def compiled?
|
@@ -206,10 +209,6 @@ module ActionView
|
|
206
209
|
|
207
210
|
private
|
208
211
|
|
209
|
-
def const_source_location_supported?
|
210
|
-
respond_to? :const_source_location # introduced in Ruby 2.7
|
211
|
-
end
|
212
|
-
|
213
212
|
def matching_views_in_source_location
|
214
213
|
return [] unless source_location
|
215
214
|
(Dir["#{source_location.chomp(File.extname(source_location))}.*{#{ActionView::Template.template_handler_extensions.join(',')}}"] - [source_location])
|
@@ -232,7 +231,7 @@ module ActionView
|
|
232
231
|
@template_errors ||=
|
233
232
|
begin
|
234
233
|
errors = []
|
235
|
-
if source_location.nil?
|
234
|
+
if source_location.nil?
|
236
235
|
# Require `#initialize` to be defined so that we can use `method#source_location`
|
237
236
|
# to look up the filename of the component.
|
238
237
|
errors << "#{self} must implement #initialize."
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "action_view/component"
|
5
|
+
|
6
|
+
module ActionView
|
7
|
+
module Component
|
8
|
+
class Engine < Rails::Engine # :nodoc:
|
9
|
+
config.action_view_component = ActiveSupport::OrderedOptions.new
|
10
|
+
|
11
|
+
initializer "action_view_component.set_configs" do |app|
|
12
|
+
options = app.config.action_view_component
|
13
|
+
|
14
|
+
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
15
|
+
|
16
|
+
if options.show_previews
|
17
|
+
options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/components/previews" : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveSupport.on_load(:action_view_component) do
|
21
|
+
options.each { |k, v| send("#{k}=", v) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
initializer "action_view_component.set_autoload_paths" do |app|
|
26
|
+
options = app.config.action_view_component
|
27
|
+
|
28
|
+
if options.show_previews && options.preview_path
|
29
|
+
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
initializer "action_view_component.eager_load_actions" do
|
34
|
+
ActiveSupport.on_load(:after_initialize) do
|
35
|
+
ActionView::Component::Base.descendants.each(&:compile)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
initializer "action_view_component.compile_config_methods" do
|
40
|
+
ActiveSupport.on_load(:action_view_component) do
|
41
|
+
config.compile_methods! if config.respond_to?(:compile_methods!)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
initializer "action_view_component.monkey_patch_render" do
|
46
|
+
ActiveSupport.on_load(:action_view) do
|
47
|
+
ActionView::Base.prepend ActionView::Component::RenderMonkeyPatch
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
config.after_initialize do |app|
|
52
|
+
options = app.config.action_view_component
|
53
|
+
|
54
|
+
if options.show_previews
|
55
|
+
app.routes.prepend do
|
56
|
+
get "/rails/components" => "rails/components#index", :internal => true
|
57
|
+
get "/rails/components/*path" => "rails/components#previews", :internal => true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,65 +1,3 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
4
|
-
require "action_view/component"
|
5
|
-
|
6
|
-
module ActionView
|
7
|
-
module Component
|
8
|
-
class Railtie < Rails::Railtie # :nodoc:
|
9
|
-
config.action_view_component = ActiveSupport::OrderedOptions.new
|
10
|
-
|
11
|
-
initializer "action_view_component.set_configs" do |app|
|
12
|
-
options = app.config.action_view_component
|
13
|
-
|
14
|
-
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
15
|
-
|
16
|
-
if options.show_previews
|
17
|
-
options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/components/previews" : nil
|
18
|
-
end
|
19
|
-
|
20
|
-
ActiveSupport.on_load(:action_view_component) do
|
21
|
-
options.each { |k, v| send("#{k}=", v) }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
initializer "action_view_component.set_autoload_paths" do |app|
|
26
|
-
require "railties/lib/rails/components_controller"
|
27
|
-
|
28
|
-
options = app.config.action_view_component
|
29
|
-
|
30
|
-
if options.show_previews && options.preview_path
|
31
|
-
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
initializer "action_view_component.eager_load_actions" do
|
36
|
-
ActiveSupport.on_load(:after_initialize) do
|
37
|
-
ActionView::Component::Base.descendants.each(&:compile)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
initializer "action_view_component.compile_config_methods" do
|
42
|
-
ActiveSupport.on_load(:action_view_component) do
|
43
|
-
config.compile_methods! if config.respond_to?(:compile_methods!)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
initializer "action_view_component.monkey_patch_render" do
|
48
|
-
ActiveSupport.on_load(:action_view) do
|
49
|
-
ActionView::Base.prepend ActionView::Component::RenderMonkeyPatch
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
config.after_initialize do |app|
|
54
|
-
options = app.config.action_view_component
|
55
|
-
|
56
|
-
if options.show_previews
|
57
|
-
app.routes.prepend do
|
58
|
-
get "/rails/components" => "rails/components#index", :internal => true
|
59
|
-
get "/rails/components/*path" => "rails/components#previews", :internal => true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
3
|
+
require "action_view/component/engine"
|
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.
|
4
|
+
version: 1.12.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-02-
|
11
|
+
date: 2020-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -157,9 +157,11 @@ files:
|
|
157
157
|
- README.md
|
158
158
|
- Rakefile
|
159
159
|
- actionview-component.gemspec
|
160
|
+
- app/controllers/rails/components_controller.rb
|
160
161
|
- lib/action_view/component.rb
|
161
162
|
- lib/action_view/component/base.rb
|
162
163
|
- lib/action_view/component/conversion.rb
|
164
|
+
- lib/action_view/component/engine.rb
|
163
165
|
- lib/action_view/component/preview.rb
|
164
166
|
- lib/action_view/component/previewable.rb
|
165
167
|
- lib/action_view/component/railtie.rb
|
@@ -182,7 +184,6 @@ files:
|
|
182
184
|
- lib/rails/generators/test_unit/component_generator.rb
|
183
185
|
- lib/rails/generators/test_unit/templates/component_test.rb.tt
|
184
186
|
- lib/railties/lib/rails.rb
|
185
|
-
- lib/railties/lib/rails/components_controller.rb
|
186
187
|
- lib/railties/lib/rails/templates/rails/components/index.html.erb
|
187
188
|
- lib/railties/lib/rails/templates/rails/components/preview.html.erb
|
188
189
|
- lib/railties/lib/rails/templates/rails/components/previews.html.erb
|