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 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