actionview-component 1.4.0 → 1.5.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/CHANGELOG.md +20 -0
- data/Gemfile.lock +4 -4
- data/README.md +60 -1
- data/lib/action_view/component.rb +5 -0
- data/lib/action_view/component/base.rb +26 -48
- data/lib/action_view/component/monkey_patch.rb +27 -0
- data/lib/action_view/component/preview.rb +106 -0
- data/lib/action_view/component/railtie.rb +58 -0
- data/lib/action_view/component/version.rb +1 -1
- data/lib/rails/generators/component/USAGE +13 -0
- data/lib/rails/generators/component/component_generator.rb +50 -0
- data/lib/rails/generators/component/templates/component.html.erb.tt +5 -0
- data/lib/rails/generators/component/templates/component.rb.tt +9 -0
- data/lib/rails/generators/test_unit/component_generator.rb +20 -0
- data/lib/rails/generators/test_unit/templates/component_test.rb.tt +12 -0
- data/lib/railties/lib/rails.rb +6 -0
- data/lib/railties/lib/rails/component_examples_controller.rb +9 -0
- data/lib/railties/lib/rails/components_controller.rb +55 -0
- data/lib/railties/lib/rails/templates/rails/components/index.html.erb +8 -0
- data/lib/railties/lib/rails/templates/rails/components/preview.html.erb +1 -0
- data/lib/railties/lib/rails/templates/rails/components/previews.html.erb +6 -0
- data/lib/railties/lib/rails/templates/rails/examples/show.html.erb +1 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0552c91192357398456b81be3efd02cfa663581acf91a07ff0cebff2b8f55a62
|
4
|
+
data.tar.gz: f945914f027bc27c0ee5397bad3a4d7ea0c1882c95500d7de67076d96f8159de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24b6e98091a0af3b3f2a0db50310d5ab6c60a59cc4bba80fdee57a6e6d34bd8535a99c9ec6183032426fdb2ddd7d41743eb9356d0552f371ca127885d906249a
|
7
|
+
data.tar.gz: aff611c2259676d8d6690e897983180c23da45b231853e0be8de61d2c0b4d2bb08340e46fa03274d2bee12366d2098721b6259205de0b4f2377365b0c37a7373
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
# v1.5.0
|
2
|
+
|
3
|
+
Note: `actionview-component` is now loaded by requiring `actionview/component`, not `actionview/component/base`.
|
4
|
+
|
5
|
+
* Fix issue with generating component method signatures.
|
6
|
+
|
7
|
+
*Ryan Workman, Dylan Clark*
|
8
|
+
|
9
|
+
* Create component generator.
|
10
|
+
|
11
|
+
*Vinicius Stock*
|
12
|
+
|
13
|
+
* Add helpers proxy.
|
14
|
+
|
15
|
+
*Kasper Meyer*
|
16
|
+
|
17
|
+
* Introduce ActionView::Component::Previews.
|
18
|
+
|
19
|
+
*Juan Manuel Ramallo*
|
20
|
+
|
1
21
|
# v1.4.0
|
2
22
|
|
3
23
|
* Fix bug where components broke in application paths with periods.
|
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.5.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -64,7 +64,7 @@ GEM
|
|
64
64
|
ast (2.4.0)
|
65
65
|
builder (3.2.3)
|
66
66
|
concurrent-ruby (1.1.5)
|
67
|
-
crass (1.0.
|
67
|
+
crass (1.0.5)
|
68
68
|
erubi (1.8.0)
|
69
69
|
globalid (0.4.2)
|
70
70
|
activesupport (>= 4.2.0)
|
@@ -74,7 +74,7 @@ GEM
|
|
74
74
|
i18n (1.6.0)
|
75
75
|
concurrent-ruby (~> 1.0)
|
76
76
|
jaro_winkler (1.5.3)
|
77
|
-
loofah (2.
|
77
|
+
loofah (2.3.1)
|
78
78
|
crass (~> 1.0.2)
|
79
79
|
nokogiri (>= 1.5.9)
|
80
80
|
mail (2.7.1)
|
@@ -87,7 +87,7 @@ GEM
|
|
87
87
|
mini_portile2 (2.4.0)
|
88
88
|
minitest (5.1.0)
|
89
89
|
nio4r (2.5.2)
|
90
|
-
nokogiri (1.10.
|
90
|
+
nokogiri (1.10.5)
|
91
91
|
mini_portile2 (~> 2.4.0)
|
92
92
|
parallel (1.17.0)
|
93
93
|
parser (2.6.3.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"
|
36
36
|
```
|
37
37
|
|
38
38
|
## Guide
|
@@ -97,10 +97,26 @@ Components are subclasses of `ActionView::Component::Base` and live in `app/comp
|
|
97
97
|
|
98
98
|
Component class names end in -`Component`.
|
99
99
|
|
100
|
+
Component module names are plural, as they are for controllers. (`Users::AvatarComponent`)
|
101
|
+
|
100
102
|
Components support ActiveModel validations. Components are validated after initialization, but before rendering.
|
101
103
|
|
102
104
|
Content passed to an `ActionView::Component` as a block is captured and assigned to the `content` accessor.
|
103
105
|
|
106
|
+
#### Quick start
|
107
|
+
|
108
|
+
Use the component generator to create a new `ActionView::Component`.
|
109
|
+
|
110
|
+
The generator accepts the component name and the list of accepted properties as arguments:
|
111
|
+
|
112
|
+
```bash
|
113
|
+
bin/rails generate component Example title content
|
114
|
+
invoke test_unit
|
115
|
+
create test/components/example_component_test.rb
|
116
|
+
create app/components/example_component.rb
|
117
|
+
create app/components/example_component.html.erb
|
118
|
+
```
|
119
|
+
|
104
120
|
#### Implementation
|
105
121
|
|
106
122
|
An `ActionView::Component` is a Ruby file and corresponding template file (in any format supported by Rails) with the same base name:
|
@@ -201,6 +217,49 @@ def test_render_component_for_tablet
|
|
201
217
|
end
|
202
218
|
```
|
203
219
|
|
220
|
+
### Previewing Components
|
221
|
+
`ActionView::Component::Preview`s provide a way to see how components look by visiting a special URL that renders them.
|
222
|
+
In the previous example, the preview class for `TestComponent` would be called `TestComponentPreview` and located in `test/components/previews/test_component_preview.rb`.
|
223
|
+
To see the preview of the component with a given title, implement a method that renders the component.
|
224
|
+
You can define as many examples as you want:
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
# test/components/previews/test_component_preview.rb
|
228
|
+
|
229
|
+
class TestComponentPreview < ActionView::Component::Preview
|
230
|
+
def with_default_title
|
231
|
+
render(TestComponent, title: "Test component default")
|
232
|
+
end
|
233
|
+
|
234
|
+
def with_long_title
|
235
|
+
render(TestComponent, title: "This is a really long title to see how the component renders this")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
```
|
239
|
+
|
240
|
+
The previews will be available in <http://localhost:3000/rails/components/test_component/with_default_title>
|
241
|
+
and <http://localhost:3000/rails/components/test_component/with_long_title>.
|
242
|
+
|
243
|
+
Previews use the application layout by default, but you can also use other layouts from your app:
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
# test/components/previews/test_component_preview.rb
|
247
|
+
|
248
|
+
class TestComponentPreview < ActionView::Component::Preview
|
249
|
+
layout "admin"
|
250
|
+
|
251
|
+
...
|
252
|
+
end
|
253
|
+
```
|
254
|
+
|
255
|
+
By default, the preview classes live in `test/components/previews`.
|
256
|
+
This can be configured using the `preview_path` option.
|
257
|
+
For example, if you want to use `lib/component_previews`, set the following in `config/application.rb`:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
config.action_view_component.preview_path = "#{Rails.root}/lib/component_previews"
|
261
|
+
```
|
262
|
+
|
204
263
|
## Frequently Asked Questions
|
205
264
|
|
206
265
|
### Can I use other templating languages besides ERB?
|
@@ -1,37 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
else
|
21
|
-
super
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
prepend RenderMonkeyPatch
|
27
|
-
end
|
3
|
+
require "active_model"
|
4
|
+
require "action_view"
|
5
|
+
require "active_support/configurable"
|
6
|
+
require_relative "preview"
|
28
7
|
|
29
8
|
module ActionView
|
30
9
|
module Component
|
31
10
|
class Base < ActionView::Base
|
32
11
|
include ActiveModel::Validations
|
33
12
|
include ActiveSupport::Configurable
|
34
|
-
include
|
13
|
+
include ActionView::Component::Previews
|
14
|
+
|
15
|
+
delegate :form_authenticity_token, :protect_against_forgery?, to: :helpers
|
35
16
|
|
36
17
|
validate :variant_exists
|
37
18
|
|
@@ -93,10 +74,14 @@ module ActionView
|
|
93
74
|
@controller ||= view_context.controller
|
94
75
|
end
|
95
76
|
|
96
|
-
#
|
77
|
+
# Provides a proxy to access helper methods through
|
78
|
+
def helpers
|
79
|
+
@helpers ||= view_context
|
80
|
+
end
|
81
|
+
|
97
82
|
# Removes the first part of the path and the extension.
|
98
83
|
def virtual_path
|
99
|
-
self.class.source_location.gsub(%r{(.*app/)|(\.rb)}, "")
|
84
|
+
self.class.source_location.gsub(%r{(.*app/components)|(\.rb)}, "")
|
100
85
|
end
|
101
86
|
|
102
87
|
def view_cache_dependencies
|
@@ -173,6 +158,15 @@ module ActionView
|
|
173
158
|
templates.map { |template| template[:variant] }
|
174
159
|
end
|
175
160
|
|
161
|
+
# we'll eventually want to update this to support other types
|
162
|
+
def type
|
163
|
+
"text/html"
|
164
|
+
end
|
165
|
+
|
166
|
+
def identifier
|
167
|
+
""
|
168
|
+
end
|
169
|
+
|
176
170
|
private
|
177
171
|
|
178
172
|
def templates
|
@@ -206,31 +200,15 @@ module ActionView
|
|
206
200
|
handler = ActionView::Template.handler_for_extension(File.extname(file_path).gsub(".", ""))
|
207
201
|
template = File.read(file_path)
|
208
202
|
|
209
|
-
# This can be removed once this code is merged into Rails
|
210
203
|
if handler.method(:call).parameters.length > 1
|
211
|
-
handler.call(
|
212
|
-
else
|
213
|
-
handler.call(
|
204
|
+
handler.call(self, template)
|
205
|
+
else # remove before upstreaming into Rails
|
206
|
+
handler.call(OpenStruct.new(source: template, identifier: identifier, type: type))
|
214
207
|
end
|
215
208
|
end
|
216
209
|
end
|
217
210
|
|
218
|
-
|
219
|
-
attr_reader :source
|
220
|
-
|
221
|
-
def initialize(source = nil)
|
222
|
-
@source = source
|
223
|
-
end
|
224
|
-
|
225
|
-
def identifier
|
226
|
-
""
|
227
|
-
end
|
228
|
-
|
229
|
-
# we'll eventually want to update this to support other types
|
230
|
-
def type
|
231
|
-
"text/html"
|
232
|
-
end
|
233
|
-
end
|
211
|
+
ActiveSupport.run_load_hooks(:action_view_component, self)
|
234
212
|
end
|
235
213
|
end
|
236
214
|
end
|
@@ -0,0 +1,27 @@
|
|
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
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
prepend RenderMonkeyPatch
|
27
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require "active_support/descendants_tracker"
|
5
|
+
require_relative "test_helpers"
|
6
|
+
|
7
|
+
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
|
+
|
29
|
+
class Preview
|
30
|
+
extend ActiveSupport::DescendantsTracker
|
31
|
+
include ActionView::Component::TestHelpers
|
32
|
+
|
33
|
+
def render(component, *locals)
|
34
|
+
render_inline(component, *locals)
|
35
|
+
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
# Returns all component preview classes.
|
39
|
+
def all
|
40
|
+
load_previews if descendants.empty?
|
41
|
+
descendants
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the html of the component in its layout
|
45
|
+
def call(example)
|
46
|
+
example_html = new.public_send(example)
|
47
|
+
|
48
|
+
Rails::ComponentExamplesController.render(template: "examples/show",
|
49
|
+
layout: @layout || "layouts/application",
|
50
|
+
assigns: { example: example_html })
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the component object class associated to the preview.
|
54
|
+
def component
|
55
|
+
self.name.sub(%r{Preview$}, "").constantize
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns all of the available examples for the component preview.
|
59
|
+
def examples
|
60
|
+
public_instance_methods(false).map(&:to_s).sort
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns +true+ if the example of the component preview exists.
|
64
|
+
def example_exists?(example)
|
65
|
+
examples.include?(example)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns +true+ if the preview exists.
|
69
|
+
def exists?(preview)
|
70
|
+
all.any? { |p| p.preview_name == preview }
|
71
|
+
end
|
72
|
+
|
73
|
+
# Find a component preview by its underscored class name.
|
74
|
+
def find(preview)
|
75
|
+
all.find { |p| p.preview_name == preview }
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the underscored name of the component preview without the suffix.
|
79
|
+
def preview_name
|
80
|
+
name.sub(/Preview$/, "").underscore
|
81
|
+
end
|
82
|
+
|
83
|
+
# Setter for layout name.
|
84
|
+
def layout(layout_name)
|
85
|
+
@layout = layout_name
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def load_previews
|
91
|
+
if preview_path
|
92
|
+
Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file| require_dependency file }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def preview_path
|
97
|
+
Base.preview_path
|
98
|
+
end
|
99
|
+
|
100
|
+
def show_previews
|
101
|
+
Base.show_previews
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "railties/lib/rails/components_controller"
|
4
|
+
require "railties/lib/rails/component_examples_controller"
|
5
|
+
|
6
|
+
module ActionView
|
7
|
+
module Component
|
8
|
+
class Railtie < Rails::Railtie # :nodoc:
|
9
|
+
config.action_view_component = ActiveSupport::OrderedOptions.new
|
10
|
+
|
11
|
+
# Disabled due to issues with ActionView::Component::Base not defining .logger
|
12
|
+
# initializer "action_view_component.logger" do
|
13
|
+
# ActiveSupport.on_load(:action_view_component) { self.logger ||= Rails.logger }
|
14
|
+
# end
|
15
|
+
|
16
|
+
initializer "action_view_component.set_configs" do |app|
|
17
|
+
options = app.config.action_view_component
|
18
|
+
|
19
|
+
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
20
|
+
|
21
|
+
if options.show_previews
|
22
|
+
options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/components/previews" : nil
|
23
|
+
end
|
24
|
+
|
25
|
+
ActiveSupport.on_load(:action_view_component) do
|
26
|
+
options.each { |k, v| send("#{k}=", v) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
initializer "action_view_component.compile_config_methods" do
|
31
|
+
ActiveSupport.on_load(:action_view_component) do
|
32
|
+
config.compile_methods! if config.respond_to?(:compile_methods!)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
initializer "action_view_component.eager_load_actions" do
|
37
|
+
ActiveSupport.on_load(:after_initialize) do
|
38
|
+
ActionView::Component::Base.descendants.each(&:action_methods) if config.eager_load
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
config.after_initialize do |app|
|
43
|
+
options = app.config.action_view_component
|
44
|
+
|
45
|
+
if options.show_previews
|
46
|
+
app.routes.prepend do
|
47
|
+
get "/rails/components" => "rails/components#index", :internal => true
|
48
|
+
get "/rails/components/*path" => "rails/components#previews", :internal => true
|
49
|
+
end
|
50
|
+
|
51
|
+
if options.preview_path
|
52
|
+
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Description:
|
2
|
+
============
|
3
|
+
Creates a new component and test.
|
4
|
+
Pass the component name, either CamelCased or under_scored, and an optional list of attributes as arguments.
|
5
|
+
|
6
|
+
Example:
|
7
|
+
========
|
8
|
+
bin/rails generate component Profile name age
|
9
|
+
|
10
|
+
creates a Profile component and test:
|
11
|
+
Component: app/components/profile_component.rb
|
12
|
+
Template: app/components/profile_component.html.erb
|
13
|
+
Test: test/components/profile_component_test.rb
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Generators
|
5
|
+
class ComponentGenerator < Rails::Generators::NamedBase
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
argument :attributes, type: :array, default: [], banner: "attribute"
|
9
|
+
hook_for :test_framework
|
10
|
+
check_class_collision suffix: "Component"
|
11
|
+
|
12
|
+
def create_component_file
|
13
|
+
template "component.rb", File.join("app/components", "#{file_name}_component.rb")
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_template_file
|
17
|
+
template "component.html.erb", File.join("app/components", "#{file_name}_component.html.erb")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def file_name
|
23
|
+
@_file_name ||= super.sub(/_component\z/i, "")
|
24
|
+
end
|
25
|
+
|
26
|
+
def requires_content?
|
27
|
+
return @requires_content if @asked
|
28
|
+
|
29
|
+
@asked = true
|
30
|
+
@requires_content = ask("Would you like #{class_name} to require content? (Y/n)").downcase == "y"
|
31
|
+
end
|
32
|
+
|
33
|
+
def parent_class
|
34
|
+
defined?(ApplicationComponent) ? "ApplicationComponent" : "ActionView::Component::Base"
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize_signature
|
38
|
+
if attributes.present?
|
39
|
+
attributes.map { |attr| "#{attr.name}:" }.join(", ")
|
40
|
+
else
|
41
|
+
"*"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize_body
|
46
|
+
attributes.map { |attr| "@#{attr.name} = #{attr.name}" }.join("\n ")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestUnit
|
4
|
+
module Generators
|
5
|
+
class ComponentGenerator < ::Rails::Generators::NamedBase
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
check_class_collision suffix: "ComponentTest"
|
8
|
+
|
9
|
+
def create_test_file
|
10
|
+
template "component_test.rb", File.join("test/components", "#{file_name}_component_test.rb")
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def file_name
|
16
|
+
@_file_name ||= super.sub(/_component\z/i, "")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class <%= class_name %>ComponentTest < ActiveSupport::TestCase
|
4
|
+
include ActionView::Component::TestHelpers
|
5
|
+
|
6
|
+
test "component renders something useful" do
|
7
|
+
# assert_equal(
|
8
|
+
# %(<span title="my title">Hello, components!</span>),
|
9
|
+
# render_inline(<%= class_name %>, attr: "value") { "Hello, components!" }.css("span").to_html
|
10
|
+
# )
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/application_controller"
|
4
|
+
load "config/application.rb" unless Rails.root
|
5
|
+
|
6
|
+
class Rails::ComponentExamplesController < ActionController::Base # :nodoc:
|
7
|
+
prepend_view_path File.expand_path("templates/rails", __dir__)
|
8
|
+
append_view_path Rails.root.join("app/views")
|
9
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/application_controller"
|
4
|
+
|
5
|
+
class Rails::ComponentsController < Rails::ApplicationController # :nodoc:
|
6
|
+
prepend_view_path File.expand_path("templates/rails", __dir__)
|
7
|
+
|
8
|
+
around_action :set_locale, only: :previews
|
9
|
+
before_action :find_preview, only: :previews
|
10
|
+
before_action :require_local!, unless: :show_previews?
|
11
|
+
|
12
|
+
if respond_to?(:content_security_policy)
|
13
|
+
content_security_policy(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
def index
|
17
|
+
@previews = ActionView::Component::Preview.all
|
18
|
+
@page_title = "Component Previews"
|
19
|
+
render template: "components/index"
|
20
|
+
end
|
21
|
+
|
22
|
+
def previews
|
23
|
+
if params[:path] == @preview.preview_name
|
24
|
+
@page_title = "Component Previews for #{@preview.preview_name}"
|
25
|
+
render template: "components/previews"
|
26
|
+
else
|
27
|
+
@example_name = File.basename(params[:path])
|
28
|
+
render template: "components/preview", layout: false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def show_previews? # :doc:
|
35
|
+
ActionView::Component::Base.show_previews
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_preview # :doc:
|
39
|
+
candidates = []
|
40
|
+
params[:path].to_s.scan(%r{/|$}) { candidates << $` }
|
41
|
+
preview = candidates.detect { |candidate| ActionView::Component::Preview.exists?(candidate) }
|
42
|
+
|
43
|
+
if preview
|
44
|
+
@preview = ActionView::Component::Preview.find(preview)
|
45
|
+
else
|
46
|
+
raise AbstractController::ActionNotFound, "Component preview '#{params[:path]}' not found"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_locale
|
51
|
+
I18n.with_locale(params[:locale] || I18n.default_locale) do
|
52
|
+
yield
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<% @previews.each do |preview| %>
|
2
|
+
<h3><%= link_to preview.preview_name.titleize, "/rails/components/#{preview.preview_name}" %></h3>
|
3
|
+
<ul>
|
4
|
+
<% preview.examples.each do |preview_example| %>
|
5
|
+
<li><%= link_to preview_example, "/rails/components/#{preview.preview_name}/#{preview_example}" %></li>
|
6
|
+
<% end %>
|
7
|
+
</ul>
|
8
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= raw @preview.call(@example_name) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= raw @example %>
|
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.5.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: 2019-11-
|
11
|
+
date: 2019-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -127,9 +127,26 @@ files:
|
|
127
127
|
- README.md
|
128
128
|
- Rakefile
|
129
129
|
- actionview-component.gemspec
|
130
|
+
- lib/action_view/component.rb
|
130
131
|
- lib/action_view/component/base.rb
|
132
|
+
- lib/action_view/component/monkey_patch.rb
|
133
|
+
- lib/action_view/component/preview.rb
|
134
|
+
- lib/action_view/component/railtie.rb
|
131
135
|
- lib/action_view/component/test_helpers.rb
|
132
136
|
- lib/action_view/component/version.rb
|
137
|
+
- lib/rails/generators/component/USAGE
|
138
|
+
- lib/rails/generators/component/component_generator.rb
|
139
|
+
- lib/rails/generators/component/templates/component.html.erb.tt
|
140
|
+
- lib/rails/generators/component/templates/component.rb.tt
|
141
|
+
- lib/rails/generators/test_unit/component_generator.rb
|
142
|
+
- lib/rails/generators/test_unit/templates/component_test.rb.tt
|
143
|
+
- lib/railties/lib/rails.rb
|
144
|
+
- lib/railties/lib/rails/component_examples_controller.rb
|
145
|
+
- lib/railties/lib/rails/components_controller.rb
|
146
|
+
- lib/railties/lib/rails/templates/rails/components/index.html.erb
|
147
|
+
- lib/railties/lib/rails/templates/rails/components/preview.html.erb
|
148
|
+
- lib/railties/lib/rails/templates/rails/components/previews.html.erb
|
149
|
+
- lib/railties/lib/rails/templates/rails/examples/show.html.erb
|
133
150
|
- script/bootstrap
|
134
151
|
- script/console
|
135
152
|
- script/install
|