actionview-component 1.6.0 → 1.6.1

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: e0d1497b59c35721a9d9c48906ca5b1a64eb30f72e9bfd17d0da2437820e7e87
4
- data.tar.gz: e703a27db8cac4a589f6d8f78e3ffc2bb7783af16d7c49c8986d06db7155bcd4
3
+ metadata.gz: 642717e715c2f33794d3647e8756af86226bf90a9ee40c28496109288fa63201
4
+ data.tar.gz: a2144dc99b735c2e0cd27b86e5f5b95f60031facc7b47af0e35f3ab0ff2562ba
5
5
  SHA512:
6
- metadata.gz: 481e35fdf095d48a1c3a33795d8e1d8b0be6a6b6944b149e5a6320add88f8748f4ea8e19282cd90bb62f9858291cd07084e9b1221051fcfb89f70b7dd6471281
7
- data.tar.gz: 45fd087cc394799a8f21044c58de91a3aeee93dc29c8fbd8ff8c4a1979977bb86bc47d38341f51a37bbe93038c81b77908ec8d634d4d41b064a11585a684ae44
6
+ metadata.gz: 34973a14a10b96e2905b2fadfa93828de4014c12f97239a367527aabea8218d13281cdc8dbad7808f9575afafb66172202612a65e51506db4f2e8be4a6055354
7
+ data.tar.gz: 893531f33aaf0982973df46acc708e42de316464a3860bda12a693e810283d12d7d5a3a5a743149fa406645ff7242f9ef04509f18a0c855379b867f6ef4f9117
@@ -1,3 +1,29 @@
1
+ # v1.6.1
2
+
3
+ * Allow Previews to have no layout.
4
+
5
+ *Jon Palmer*
6
+
7
+ * Bump rack from 2.0.7 to 2.0.8.
8
+
9
+ *Dependabot*
10
+
11
+ * Compile components on application boot when eager loading is enabled.
12
+
13
+ *Joel Hawksley*
14
+
15
+ * Previews support content blocks.
16
+
17
+ *Cesario Uy*
18
+
19
+ * Follow Rails conventions. (refactor)
20
+
21
+ *Rainer Borene*
22
+
23
+ * Fix edge case issue with extracting variants from less conventional source_locations.
24
+
25
+ *Ryan Workman*
26
+
1
27
  # v1.6.0
2
28
 
3
29
  * Avoid dropping elements in the render_inline test helper.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- actionview-component (1.6.0)
4
+ actionview-component (1.6.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -101,7 +101,7 @@ GEM
101
101
  parallel (1.17.0)
102
102
  parser (2.6.3.0)
103
103
  ast (~> 2.4.0)
104
- rack (2.0.7)
104
+ rack (2.0.8)
105
105
  rack-test (1.1.0)
106
106
  rack (>= 1.0, < 3)
107
107
  rails (6.0.0)
data/README.md CHANGED
@@ -32,7 +32,7 @@ $ bundle
32
32
  In `config/application.rb`, add:
33
33
 
34
34
  ```bash
35
- require "action_view/component"
35
+ require "action_view/component/railtie"
36
36
  ```
37
37
 
38
38
  ## Guide
@@ -174,7 +174,7 @@ Example for a `Post` model:
174
174
  `render(@post)`
175
175
 
176
176
  ```ruby
177
- class PostComponent < ActionView::Component
177
+ class PostComponent < ActionView::Component::Base
178
178
  def initialize(post)
179
179
  @post = post
180
180
  end
@@ -204,12 +204,10 @@ An error will be raised:
204
204
  Components are unit tested directly. The `render_inline` test helper wraps the result in `Nokogiri.HTML`, allowing us to test the component above as:
205
205
 
206
206
  ```ruby
207
- require "action_view/component/test_helpers"
208
-
209
- class MyComponentTest < Minitest::Test
210
- include ActionView::Component::TestHelpers
207
+ require "action_view/component/test_case"
211
208
 
212
- def test_render_component
209
+ class MyComponentTest < ActionView::Component::TestCase
210
+ test "render component" do
213
211
  assert_equal(
214
212
  %(<span title="my title">Hello, World!</span>),
215
213
  render_inline(TestComponent, title: "my title") { "Hello, World!" }.to_html
@@ -225,7 +223,7 @@ In general, we’ve found it makes the most sense to test components based on th
225
223
  To test a specific variant you can wrap your test with the `with_variant` helper method as:
226
224
 
227
225
  ```ruby
228
- def test_render_component_for_tablet
226
+ test "render component for tablet" do
229
227
  with_variant :tablet do
230
228
  assert_equal(
231
229
  %(<span title="my title">Hello, tablets!</span>),
@@ -1,6 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "action_view/component/monkey_patch"
4
- require "action_view/component/active_model_conversion_monkey_patch"
5
- require "action_view/component/base"
3
+ require "active_model"
4
+ require "action_view"
5
+ require "active_support/dependencies/autoload"
6
6
  require "action_view/component/railtie"
7
+
8
+ module ActionView
9
+ module Component
10
+ extend ActiveSupport::Autoload
11
+
12
+ autoload :Base
13
+ autoload :Conversion
14
+ autoload :Preview
15
+ autoload :Previewable
16
+ autoload :TestHelpers
17
+ autoload :TestCase
18
+ autoload :RenderMonkeyPatch
19
+ end
20
+ end
21
+
22
+ ActiveModel::Conversion.include ActionView::Component::Conversion
@@ -1,16 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_model"
4
- require "action_view"
5
3
  require "active_support/configurable"
6
- require_relative "preview"
7
4
 
8
5
  module ActionView
9
6
  module Component
10
7
  class Base < ActionView::Base
11
8
  include ActiveModel::Validations
12
9
  include ActiveSupport::Configurable
13
- include ActionView::Component::Previews
10
+ include ActionView::Component::Previewable
14
11
 
15
12
  delegate :form_authenticity_token, :protect_against_forgery?, to: :helpers
16
13
 
@@ -113,6 +110,10 @@ module ActionView
113
110
  end
114
111
  end
115
112
 
113
+ def has_initializer?
114
+ self.instance_method(:initialize).owner == self
115
+ end
116
+
116
117
  def source_location
117
118
  # Require #initialize to be defined so that we can use
118
119
  # method#source_location to look up the file name
@@ -121,16 +122,26 @@ module ActionView
121
122
  # If we were able to only support Ruby 2.7+,
122
123
  # We could just use Module#const_source_location,
123
124
  # rendering this unnecessary.
124
- raise NotImplementedError.new("#{self} must implement #initialize.") unless self.instance_method(:initialize).owner == self
125
+ raise NotImplementedError.new("#{self} must implement #initialize.") unless has_initializer?
125
126
 
126
127
  instance_method(:initialize).source_location[0]
127
128
  end
128
129
 
130
+ def eager_load!
131
+ self.descendants.each do |descendant|
132
+ descendant.compile if descendant.has_initializer?
133
+ end
134
+ end
135
+
136
+ def compiled?
137
+ @compiled && ActionView::Base.cache_template_loading
138
+ end
139
+
129
140
  # Compile templates to instance methods, assuming they haven't been compiled already.
130
141
  # We could in theory do this on app boot, at least in production environments.
131
142
  # Right now this just compiles the first time the component is rendered.
132
143
  def compile
133
- return if @compiled && ActionView::Base.cache_template_loading
144
+ return if compiled?
134
145
 
135
146
  validate_templates
136
147
 
@@ -161,13 +172,19 @@ module ActionView
161
172
 
162
173
  private
163
174
 
175
+ def matching_views_in_source_location
176
+ (Dir["#{source_location.sub(/#{File.extname(source_location)}$/, '')}.*{#{ActionView::Template.template_handler_extensions.join(',')}}"] - [source_location])
177
+ end
178
+
164
179
  def templates
165
180
  @templates ||=
166
- (Dir["#{source_location.sub(/#{File.extname(source_location)}$/, '')}.*{#{ActionView::Template.template_handler_extensions.join(',')}}"] - [source_location]).each_with_object([]) do |path, memo|
181
+ matching_views_in_source_location.each_with_object([]) do |path, memo|
182
+ pieces = File.basename(path).split(".")
183
+
167
184
  memo << {
168
185
  path: path,
169
- variant: path.split(".").second.split("+")[1]&.to_sym,
170
- handler: path.split(".").last
186
+ variant: pieces.second.split("+")[1]&.to_sym,
187
+ handler: pieces.last
171
188
  }
172
189
  end
173
190
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Component # :nodoc:
5
+ module Conversion
6
+ def to_component_class
7
+ "#{self.class.name}Component".safe_constantize
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,37 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/concern"
4
3
  require "active_support/descendants_tracker"
5
- require_relative "test_helpers"
6
4
 
7
5
  module ActionView
8
- module Component #:nodoc:
9
- module Previews
10
- extend ActiveSupport::Concern
11
-
12
- included do
13
- # Set the location of component previews through app configuration:
14
- #
15
- # config.action_view_component.preview_path = "#{Rails.root}/lib/component_previews"
16
- #
17
- mattr_accessor :preview_path, instance_writer: false
18
-
19
- # Enable or disable component previews through app configuration:
20
- #
21
- # config.action_view_component.show_previews = true
22
- #
23
- # Defaults to +true+ for development environment
24
- #
25
- mattr_accessor :show_previews, instance_writer: false
26
- end
27
- end
28
-
6
+ module Component # :nodoc:
29
7
  class Preview
30
8
  extend ActiveSupport::DescendantsTracker
31
9
  include ActionView::Component::TestHelpers
32
10
 
33
- def render(component, *locals)
34
- render_inline(component, *locals)
11
+ def render(component, *locals, &block)
12
+ render_inline(component, *locals, &block)
35
13
  end
36
14
 
37
15
  class << self
@@ -42,11 +20,14 @@ module ActionView
42
20
  end
43
21
 
44
22
  # Returns the html of the component in its layout
45
- def call(example)
23
+ def call(example, layout: nil)
46
24
  example_html = new.public_send(example)
25
+ if layout.nil?
26
+ layout = @layout.nil? ? "layouts/application" : @layout
27
+ end
47
28
 
48
29
  Rails::ComponentExamplesController.render(template: "examples/show",
49
- layout: @layout || "layouts/application",
30
+ layout: layout,
50
31
  assigns: { example: example_html })
51
32
  end
52
33
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActionView
6
+ module Component # :nodoc:
7
+ module Previewable
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ # Set the location of component previews through app configuration:
12
+ #
13
+ # config.action_view_component.preview_path = "#{Rails.root}/lib/component_previews"
14
+ #
15
+ mattr_accessor :preview_path, instance_writer: false
16
+
17
+ # Enable or disable component previews through app configuration:
18
+ #
19
+ # config.action_view_component.show_previews = true
20
+ #
21
+ # Defaults to +true+ for development environment
22
+ #
23
+ mattr_accessor :show_previews, instance_writer: false
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails"
4
+
3
5
  module ActionView
4
6
  module Component
5
7
  class Railtie < Rails::Railtie # :nodoc:
@@ -23,6 +25,7 @@ module ActionView
23
25
  require "railties/lib/rails/components_controller"
24
26
  require "railties/lib/rails/component_examples_controller"
25
27
 
28
+ app.config.eager_load_namespaces << ActionView::Component::Base
26
29
  options = app.config.action_view_component
27
30
 
28
31
  if options.show_previews && options.preview_path
@@ -36,6 +39,12 @@ module ActionView
36
39
  end
37
40
  end
38
41
 
42
+ initializer "action_view_component.monkey_patch_render" do
43
+ ActiveSupport.on_load(:action_view) do
44
+ ActionView::Base.prepend ActionView::Component::RenderMonkeyPatch
45
+ end
46
+ end
47
+
39
48
  config.after_initialize do |app|
40
49
  options = app.config.action_view_component
41
50
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Monkey patch ActionView::Base#render to support ActionView::Component
4
+ #
5
+ # A version of this monkey patch was upstreamed in https://github.com/rails/rails/pull/36388
6
+ # We'll need to upstream an updated version of this eventually.
7
+ module ActionView
8
+ module Component
9
+ module RenderMonkeyPatch # :nodoc:
10
+ def render(options = {}, args = {}, &block)
11
+ if options.respond_to?(:render_in)
12
+ ActiveSupport::Deprecation.warn(
13
+ "passing component instances (`render MyComponent.new(foo: :bar)`) has been deprecated and will be removed in v2.0.0. Use `render MyComponent, foo: :bar` instead."
14
+ )
15
+
16
+ options.render_in(self, &block)
17
+ elsif options.is_a?(Class) && options < ActionView::Component::Base
18
+ options.new(args).render_in(self, &block)
19
+ elsif options.is_a?(Hash) && options.has_key?(:component)
20
+ options[:component].new(options[:locals]).render_in(self, &block)
21
+ elsif options.respond_to?(:to_component_class) && !options.to_component_class.nil?
22
+ options.to_component_class.new(options).render_in(self, &block)
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/test_case"
4
+
5
+ module ActionView
6
+ module Component
7
+ class TestCase < ActiveSupport::TestCase
8
+ include ActionView::Component::TestHelpers
9
+ end
10
+ end
11
+ end
@@ -5,7 +5,7 @@ module ActionView
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 6
8
- PATCH = 0
8
+ PATCH = 1
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
@@ -1,8 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- class <%= class_name %>ComponentTest < ActiveSupport::TestCase
4
- include ActionView::Component::TestHelpers
5
-
3
+ class <%= class_name %>ComponentTest < ActionView::Component::TestCase
6
4
  test "component renders something useful" do
7
5
  # assert_equal(
8
6
  # %(<span title="my title">Hello, components!</span>),
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.6.0
4
+ version: 1.6.1
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: 2019-12-11 00:00:00.000000000 Z
11
+ date: 2019-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -142,11 +142,13 @@ files:
142
142
  - Rakefile
143
143
  - actionview-component.gemspec
144
144
  - lib/action_view/component.rb
145
- - lib/action_view/component/active_model_conversion_monkey_patch.rb
146
145
  - lib/action_view/component/base.rb
147
- - lib/action_view/component/monkey_patch.rb
146
+ - lib/action_view/component/conversion.rb
148
147
  - lib/action_view/component/preview.rb
148
+ - lib/action_view/component/previewable.rb
149
149
  - lib/action_view/component/railtie.rb
150
+ - lib/action_view/component/render_monkey_patch.rb
151
+ - lib/action_view/component/test_case.rb
150
152
  - lib/action_view/component/test_helpers.rb
151
153
  - lib/action_view/component/version.rb
152
154
  - lib/rails/generators/component/USAGE
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- module Conversion
5
- def to_component_class
6
- "#{self.class.name}Component".safe_constantize
7
- end
8
- end
9
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Monkey patch ActionView::Base#render to support ActionView::Component
4
- #
5
- # A version of this monkey patch was upstreamed in https://github.com/rails/rails/pull/36388
6
- # We'll need to upstream an updated version of this eventually.
7
- class ActionView::Base
8
- module RenderMonkeyPatch
9
- def render(options = {}, args = {}, &block)
10
- if options.respond_to?(:render_in)
11
- ActiveSupport::Deprecation.warn(
12
- "passing component instances (`render MyComponent.new(foo: :bar)`) has been deprecated and will be removed in v2.0.0. Use `render MyComponent, foo: :bar` instead."
13
- )
14
-
15
- options.render_in(self, &block)
16
- elsif options.is_a?(Class) && options < ActionView::Component::Base
17
- options.new(args).render_in(self, &block)
18
- elsif options.is_a?(Hash) && options.has_key?(:component)
19
- options[:component].new(options[:locals]).render_in(self, &block)
20
- elsif options.respond_to?(:to_component_class) && !options.to_component_class.nil?
21
- options.to_component_class.new(options).render_in(self, &block)
22
- else
23
- super
24
- end
25
- end
26
- end
27
-
28
- prepend RenderMonkeyPatch
29
- end