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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c64114f4ba9a12fb68d0157a9f10a9fc423d09dbc181f0fd9f403671b61a047
4
- data.tar.gz: 3c6306682e37e6f9f4d9ed66564130a225f122aaa71caffdd3ab063ad70524c3
3
+ metadata.gz: cfaa667b7c02706e492cb8f92221bcc2ec39137b525faccdaadbef76435c9880
4
+ data.tar.gz: b9bf382421e68d742e5427b67b5b84163cbca8c47fca9e6789391ceea4bc5f2e
5
5
  SHA512:
6
- metadata.gz: b92ca951edd213245c3d0b473fe87650e0c87f4130a89bd4f628d7df0636fab794853943c172f57c10b648b43a98d7dfcca228be05d4c8120930b0ad5fb06683
7
- data.tar.gz: 12bac559a2d557e72bbec729ae8402fcc08a8cc2f3c38d57eea332aa32391df4018447954c0b2e644076683573b55b70f7b02868524353645eca663abae5609c
6
+ metadata.gz: 8563f9ef8e370a5a0dfdc15813e72b2dd35c6f0b37de6fa81ba84a50b20427049d0e00fc5ecbb72ff4f15bb50e0793e5afcaf59ac85d3d5b78e4091b7080ca79
7
+ data.tar.gz: 5447df2d42fddbb35b90d05e328e3de3c78d7db2a44d92a29de49986630b9dbc2203012bc9fdc48812422b8a761e881f0d106e0d8abb55ed412b07687c00d0dd
@@ -23,3 +23,5 @@ context or references to similar behavior in other libraries? -->
23
23
  **Rails version**:
24
24
 
25
25
  **Ruby version**:
26
+
27
+ **Gem version**:
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.11.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.5)
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.6.0)
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
- This gem is meant to serve as a precursor to upstreaming the `ActionView::Component` class into Rails. It also serves to enable the usage of `ActionView::Component` in older versions of Rails.
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
- Preliminary support for rendering components was merged into Rails `6.1.0.alpha` in https://github.com/rails/rails/pull/36388. Assuming `ActionView::Component` makes it into Rails, this gem will then exist to serve as a backport.
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
- As the goal of this gem is to be upstreamed into Rails, it is designed to integrate as seamlessly as possible, with the [least surprise](https://www.artima.com/intv/ruby4.html).
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 %>"></div>
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
- <% help_enabled? && component.with(:header) do %>
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 %>"></div>
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 < ApplicationComponent
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
- In Ruby 2.6.x and below, ActionView::Component requires the presence of an `initialize` method in each component.
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
- render template: "components/index"
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
- render template: "components/previews"
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
- render template: "components/preview", **opts
36
+ # rubocop:disable GitHub/RailsControllerRenderPathsExist
37
+ render "components/preview", **opts
38
+ # rubocop:enable GitHub/RailsControllerRenderPathsExist
33
39
  end
34
40
  end
35
41
 
@@ -3,7 +3,7 @@
3
3
  require "active_model"
4
4
  require "action_view"
5
5
  require "active_support/dependencies/autoload"
6
- require "action_view/component/railtie"
6
+ require "action_view/component/engine"
7
7
 
8
8
  module ActionView
9
9
  module Component
@@ -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. Called by ActionView::Base#render.
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, title: "greeting" do %>world<% end %>
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, *args, &block)
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
- validate!
57
-
58
- return "" unless render?
55
+ before_render_check
59
56
 
60
- send(self.class.call_method_name(@variant))
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
- if const_source_location_supported?
146
- const_source_location(self.name)[0]
147
- else
148
- # Require `#initialize` to be defined so that we can use `method#source_location`
149
- # to look up the filename of the component.
150
- initialize_method = instance_method(:initialize)
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? && !const_source_location_supported?
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 "rails"
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"
@@ -4,8 +4,8 @@ module ActionView
4
4
  module Component
5
5
  module VERSION
6
6
  MAJOR = 1
7
- MINOR = 11
8
- PATCH = 1
7
+ MINOR = 12
8
+ PATCH = 0
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  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.11.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-19 00:00:00.000000000 Z
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