actionview-component 1.11.1 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|