superview 0.1.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +21 -16
- data/README.md +89 -28
- data/lib/superview/actions.rb +22 -21
- data/lib/superview/version.rb +1 -1
- metadata +36 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76c8014ae40d2045b7ad8f93e8005aa7f3af1cfc7568579e2dea783c16c94840
|
4
|
+
data.tar.gz: db2d98cf482c7c8055a58758b3c409f6f48694fd6b114fe5045803cbac53cf96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92697e127638e7ca678b97ca776131a9e4ca1ccae741b62bab41deea80e6e6d268fb7d37abff2dc0dbae9004e0a6973ff56c51fa1bbb6a7a40d1cd1f7c82d4ba
|
7
|
+
data.tar.gz: a806923fbf0f9048b9deafe38a8eb1f5f2ed933acb0095c38c222f17c01e0378c6518931018ece0d41b41d70659e519dae641d467f6f6d04bebc041c0ea23bcf
|
data/Gemfile.lock
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
superview (0.
|
5
|
-
phlex-rails (>= 1.0, < 3.0)
|
4
|
+
superview (1.0.0)
|
6
5
|
zeitwerk (~> 2.0)
|
7
6
|
|
8
7
|
GEM
|
9
8
|
remote: https://rubygems.org/
|
10
9
|
specs:
|
11
|
-
actionpack (
|
12
|
-
actionview (=
|
13
|
-
activesupport (=
|
10
|
+
actionpack (7.2.2.1)
|
11
|
+
actionview (= 7.2.2.1)
|
12
|
+
activesupport (= 7.2.2.1)
|
14
13
|
nokogiri (>= 1.8.5)
|
15
|
-
|
14
|
+
racc
|
15
|
+
rack (>= 2.2.4, < 3.2)
|
16
16
|
rack-session (>= 1.0.1)
|
17
17
|
rack-test (>= 0.6.3)
|
18
18
|
rails-dom-testing (~> 2.2)
|
19
19
|
rails-html-sanitizer (~> 1.6)
|
20
20
|
useragent (~> 0.16)
|
21
|
-
actionview (
|
22
|
-
activesupport (=
|
21
|
+
actionview (7.2.2.1)
|
22
|
+
activesupport (= 7.2.2.1)
|
23
23
|
builder (~> 3.1)
|
24
24
|
erubi (~> 1.11)
|
25
25
|
rails-dom-testing (~> 2.2)
|
26
26
|
rails-html-sanitizer (~> 1.6)
|
27
|
-
activesupport (
|
27
|
+
activesupport (7.2.2.1)
|
28
28
|
base64
|
29
29
|
benchmark (>= 0.3)
|
30
30
|
bigdecimal
|
@@ -36,7 +36,6 @@ GEM
|
|
36
36
|
minitest (>= 5.1)
|
37
37
|
securerandom (>= 0.3)
|
38
38
|
tzinfo (~> 2.0, >= 2.0.5)
|
39
|
-
uri (>= 0.13.1)
|
40
39
|
base64 (0.2.0)
|
41
40
|
benchmark (0.4.0)
|
42
41
|
bigdecimal (3.1.8)
|
@@ -58,10 +57,11 @@ GEM
|
|
58
57
|
loofah (2.23.1)
|
59
58
|
crass (~> 1.0.2)
|
60
59
|
nokogiri (>= 1.12.0)
|
60
|
+
method_source (1.1.0)
|
61
61
|
minitest (5.25.4)
|
62
|
-
nokogiri (1.
|
62
|
+
nokogiri (1.18.0-arm64-darwin)
|
63
63
|
racc (~> 1.4)
|
64
|
-
nokogiri (1.
|
64
|
+
nokogiri (1.18.0-x86_64-linux-gnu)
|
65
65
|
racc (~> 1.4)
|
66
66
|
phlex (1.11.0)
|
67
67
|
phlex-rails (1.2.2)
|
@@ -85,9 +85,9 @@ GEM
|
|
85
85
|
rails-html-sanitizer (1.6.2)
|
86
86
|
loofah (~> 2.21)
|
87
87
|
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
88
|
-
railties (
|
89
|
-
actionpack (=
|
90
|
-
activesupport (=
|
88
|
+
railties (7.2.2.1)
|
89
|
+
actionpack (= 7.2.2.1)
|
90
|
+
activesupport (= 7.2.2.1)
|
91
91
|
irb (~> 1.13)
|
92
92
|
rackup (>= 1.0.0)
|
93
93
|
rake (>= 12.2)
|
@@ -120,8 +120,11 @@ GEM
|
|
120
120
|
thor (1.3.2)
|
121
121
|
tzinfo (2.0.6)
|
122
122
|
concurrent-ruby (~> 1.0)
|
123
|
-
uri (1.0.2)
|
124
123
|
useragent (0.16.11)
|
124
|
+
view_component (3.0.0)
|
125
|
+
activesupport (>= 5.2.0, < 8.0)
|
126
|
+
concurrent-ruby (~> 1.0)
|
127
|
+
method_source (~> 1.0)
|
125
128
|
zeitwerk (2.7.1)
|
126
129
|
|
127
130
|
PLATFORMS
|
@@ -131,9 +134,11 @@ PLATFORMS
|
|
131
134
|
x86_64-linux
|
132
135
|
|
133
136
|
DEPENDENCIES
|
137
|
+
phlex-rails (>= 1.0, < 3.0)
|
134
138
|
rake (~> 13.0)
|
135
139
|
rspec-rails (~> 7.0)
|
136
140
|
superview!
|
141
|
+
view_component (~> 3.0.0)
|
137
142
|
|
138
143
|
BUNDLED WITH
|
139
144
|
2.4.8
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Superview
|
2
2
|
|
3
|
-
Build Rails applications, from the ground up, using [Phlex](https://www.phlex.fun/) components, like this.
|
3
|
+
Build Rails applications, from the ground up, using [Phlex](https://www.phlex.fun/) or [ViewComponent](https://viewcomponent.org/) components, like this.
|
4
4
|
|
5
5
|
```ruby
|
6
|
+
# ./app/controllers/posts_controller.rb
|
6
7
|
class PostsController < ApplicationController
|
7
8
|
include Superview::Actions
|
8
9
|
|
@@ -17,6 +18,21 @@ class PostsController < ApplicationController
|
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
21
|
+
class Edit < ViewComponent::Base
|
22
|
+
attr_accessor :post
|
23
|
+
|
24
|
+
def call
|
25
|
+
<<~HTML
|
26
|
+
<h1>Edit #{@post.title}</h1>
|
27
|
+
<form action="<%= post_path(@post) %>" method="post">
|
28
|
+
<input type="text" name="title" value="<%= @post.title %>">
|
29
|
+
<textarea name="body"><%= @post.body %></textarea>
|
30
|
+
<button type="submit">Save</button>
|
31
|
+
</form>
|
32
|
+
HTML
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
20
36
|
private
|
21
37
|
def load_post
|
22
38
|
@post = Post.find(params[:id])
|
@@ -41,13 +57,22 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
41
57
|
|
42
58
|
## Usage
|
43
59
|
|
44
|
-
|
60
|
+
Add `include Superview::Actions` to any controllers you'd like to render components as controller actions.
|
45
61
|
|
46
|
-
|
62
|
+
```ruby
|
63
|
+
# ./app/controllers/posts_controller.rb
|
64
|
+
class PostsController < ApplicationController
|
65
|
+
# 🚨 Add this 👇 to your controller 🚨
|
66
|
+
include Superview::Actions
|
47
67
|
|
48
|
-
|
68
|
+
# Your code...
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
Then add classes to your controller that map to the actions you'd like to render. The `Show` class will render when the `PostsController#show` action is called and the `Edit` class will render when the `PostsController#edit` action is called.
|
49
73
|
|
50
74
|
```ruby
|
75
|
+
# ./app/controllers/posts_controller.rb
|
51
76
|
class PostsController < ApplicationController
|
52
77
|
include Superview::Actions
|
53
78
|
|
@@ -62,6 +87,21 @@ class PostsController < ApplicationController
|
|
62
87
|
end
|
63
88
|
end
|
64
89
|
|
90
|
+
class Edit < ViewComponent::Base
|
91
|
+
attr_accessor :post
|
92
|
+
|
93
|
+
def call
|
94
|
+
<<~HTML
|
95
|
+
<h1>Edit #{@post.title}</h1>
|
96
|
+
<form action="<%= post_path(@post) %>" method="post">
|
97
|
+
<input type="text" name="title" value="<%= @post.title %>">
|
98
|
+
<textarea name="body"><%= @post.body %></textarea>
|
99
|
+
<button type="submit">Save</button>
|
100
|
+
</form>
|
101
|
+
HTML
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
65
105
|
private
|
66
106
|
def load_post
|
67
107
|
@post = Post.find(params[:id])
|
@@ -69,13 +109,16 @@ class PostsController < ApplicationController
|
|
69
109
|
end
|
70
110
|
```
|
71
111
|
|
72
|
-
|
112
|
+
### Explicit rendering
|
113
|
+
|
114
|
+
You can explicitly render a component in a controller action method. In this example, we needed to render a the `Show` component in the `html` format and a JSON response in the `json` format.
|
73
115
|
|
74
116
|
```ruby
|
117
|
+
# ./app/controllers/posts_controller.rb
|
75
118
|
class PostsController < ApplicationController
|
76
119
|
include Superview::Actions
|
77
120
|
|
78
|
-
|
121
|
+
# Your code...
|
79
122
|
|
80
123
|
class Show < ApplicationComponent
|
81
124
|
attr_accessor :post
|
@@ -88,28 +131,28 @@ class PostsController < ApplicationController
|
|
88
131
|
|
89
132
|
def show
|
90
133
|
respond_to do |format|
|
91
|
-
|
92
|
-
|
134
|
+
# 👋 Renders the Show component
|
135
|
+
format.html { render component }
|
136
|
+
|
137
|
+
# 👉 These would also work...
|
93
138
|
# format.html { render Show.new.tap { _1.post = @post } }
|
94
|
-
# format.html { render
|
95
|
-
# format.html { render
|
96
|
-
# format.html { render
|
139
|
+
# format.html { render component Show.new }
|
140
|
+
# format.html { render component Show }
|
141
|
+
# format.html { render component :show }
|
97
142
|
format.json { render json: @post }
|
98
143
|
end
|
99
144
|
end
|
100
145
|
|
101
|
-
|
102
|
-
def load_post
|
103
|
-
@post = Post.find(params[:id])
|
104
|
-
end
|
146
|
+
# Your code...
|
105
147
|
end
|
106
148
|
```
|
107
149
|
|
108
|
-
### Rendering other
|
150
|
+
### Rendering other classes from different actions
|
109
151
|
|
110
|
-
It's common to have to render form actions from other actions when forms are saved. In this example the `create` method renders the `
|
152
|
+
It's common to have to render form actions from other actions when forms are saved. In this example the `create` method renders the `component New` view when the form is invalid.
|
111
153
|
|
112
154
|
```ruby
|
155
|
+
# ./app/controllers/posts_controller.rb
|
113
156
|
class PostsController < ApplicationController
|
114
157
|
include Superview::Actions
|
115
158
|
|
@@ -119,21 +162,19 @@ class PostsController < ApplicationController
|
|
119
162
|
if @post.save
|
120
163
|
redirect_to @post
|
121
164
|
else
|
122
|
-
|
123
|
-
|
165
|
+
# 👋 Renders the New component from the create action.
|
166
|
+
render component New
|
167
|
+
|
168
|
+
# 👉 These would also work...
|
124
169
|
# render New.new.tap { _1.post = @post }
|
125
|
-
# render
|
126
|
-
# render
|
127
|
-
# render
|
170
|
+
# render component New.new
|
171
|
+
# render component New
|
172
|
+
# render component :new
|
128
173
|
end
|
129
174
|
end
|
130
175
|
|
131
|
-
|
132
|
-
def load_post
|
133
|
-
@post = Post.find(params[:id])
|
134
|
-
end
|
176
|
+
# Your code...
|
135
177
|
end
|
136
|
-
|
137
178
|
```
|
138
179
|
|
139
180
|
### Extracting inline views into the `./app/views` folder
|
@@ -159,9 +200,11 @@ end
|
|
159
200
|
Then include the `Posts` module in the controllers you'd like to use the views:
|
160
201
|
|
161
202
|
```ruby
|
203
|
+
# ./app/controllers/posts_controller.rb
|
162
204
|
class PostsController < ApplicationController
|
163
205
|
include Superview::Actions
|
164
|
-
|
206
|
+
# 🚨 Add this 👇 to your controller 🚨
|
207
|
+
include Posts
|
165
208
|
|
166
209
|
before_action :load_post
|
167
210
|
|
@@ -181,6 +224,24 @@ end
|
|
181
224
|
|
182
225
|
That's it! Ruby includes all the classes in the `Posts` module, which Superview picks up and renders in the controller. If you have an `Index`, `Edit`, `New`, etc. class in the `Posts` namespace, those would be implicitly rendered for their respective action.
|
183
226
|
|
227
|
+
### View path class mappings
|
228
|
+
|
229
|
+
Not all component libraries are integrated into Rails views, so you might have to manually configure the view paths in your Rails application. This instructs the Rails code reloader, Zeitwerk, to load the components.
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
# ./config/application.rb
|
233
|
+
module MyApp
|
234
|
+
class Application < Rails::Application
|
235
|
+
config.autoload_paths << "#{root}/app/views"
|
236
|
+
config.autoload_paths << "#{root}/app/views/layouts"
|
237
|
+
config.autoload_paths << "#{root}/app/views/components"
|
238
|
+
# Your code
|
239
|
+
end
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
243
|
+
For example, the `Show` component in the `Posts` module would be loaded from `./app/views/posts/show.rb` and the `Layout` component in the `Layouts` module would be loaded from `./app/views/layouts/layout.rb`.
|
244
|
+
|
184
245
|
## Development
|
185
246
|
|
186
247
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/superview/actions.rb
CHANGED
@@ -37,7 +37,7 @@ module Superview
|
|
37
37
|
# Finds a class on the controller with the same name as the action. For example,
|
38
38
|
# `def index` would find the `Index` constant on the controller class to render
|
39
39
|
# for the action `index`.
|
40
|
-
def
|
40
|
+
def component_action_class(action:)
|
41
41
|
action_class = action.to_s.camelcase
|
42
42
|
const_get action_class if const_defined? action_class
|
43
43
|
end
|
@@ -49,7 +49,7 @@ module Superview
|
|
49
49
|
# on Phlex. For example, if a controller defines @users and a Phlex class has
|
50
50
|
# `attr_writer :users`, `attr_accessor :user`, or `def users=`, it will be automatically
|
51
51
|
# set by this method.
|
52
|
-
def
|
52
|
+
def assign_component_accessors(view)
|
53
53
|
view.tap do |view|
|
54
54
|
view_assigns.each do |variable, value|
|
55
55
|
attr_writer_name = "#{variable}="
|
@@ -59,44 +59,45 @@ module Superview
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# Initializers a Phlex view based on the action name and assigns accessors
|
62
|
-
def
|
63
|
-
|
62
|
+
def component_action(action)
|
63
|
+
component_view self.class.component_action_class(action: action)
|
64
64
|
end
|
65
65
|
|
66
|
-
# Initializes a
|
67
|
-
def
|
68
|
-
|
66
|
+
# Initializes a component view class and assigns accessors.
|
67
|
+
def component_view(view_class)
|
68
|
+
assign_component_accessors view_class.new
|
69
69
|
end
|
70
70
|
|
71
71
|
# Phlex action for the current action.
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
phlex_view target
|
72
|
+
def component(target = action_name)
|
73
|
+
if target.is_a? Class
|
74
|
+
component_view target
|
75
|
+
elsif target.respond_to? :render_in
|
76
|
+
assign_component_accessors target
|
77
|
+
else
|
78
|
+
component_action target
|
80
79
|
end
|
81
80
|
end
|
82
81
|
|
82
|
+
alias :phlex :component
|
83
|
+
|
83
84
|
# Checks if a Phlex class name is present for a controller action name
|
84
|
-
def
|
85
|
-
self.class.
|
85
|
+
def component_action_exists?(action)
|
86
|
+
self.class.component_action_class(action: action).present?
|
86
87
|
end
|
87
88
|
|
88
89
|
# This is a built-in Rails method resolves the method to call for an action.
|
89
90
|
# If it resolves a Phlex class in the controller, it will render that. If it's
|
90
91
|
# not found it continues with Rails method of resolving action names.
|
91
92
|
def method_for_action(action_name)
|
92
|
-
super || if
|
93
|
-
"
|
93
|
+
super || if component_action_exists? action_name
|
94
|
+
"default_component_render"
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
97
98
|
# Renders a Phlex view for the given action, if it's present.
|
98
|
-
def
|
99
|
-
render
|
99
|
+
def default_component_render
|
100
|
+
render component
|
100
101
|
end
|
101
102
|
end
|
102
103
|
end
|
data/lib/superview/version.rb
CHANGED
metadata
CHANGED
@@ -1,50 +1,65 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: superview
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Gessler
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: zeitwerk
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.0'
|
20
|
-
- - "<"
|
17
|
+
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
19
|
+
version: '2.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.0'
|
30
|
-
- - "<"
|
24
|
+
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
26
|
+
version: '2.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
28
|
+
name: view_component
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
31
|
- - "~>"
|
38
32
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
40
|
-
type: :
|
33
|
+
version: 3.0.0
|
34
|
+
type: :development
|
41
35
|
prerelease: false
|
42
36
|
version_requirements: !ruby/object:Gem::Requirement
|
43
37
|
requirements:
|
44
38
|
- - "~>"
|
45
39
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
47
|
-
|
40
|
+
version: 3.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: phlex-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '3.0'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.0'
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.0'
|
61
|
+
description: Build Rails applications entirely from Phlex, ViewComponents, or any
|
62
|
+
object that responds to `#render_in`
|
48
63
|
email:
|
49
64
|
- bradgessler@gmail.com
|
50
65
|
executables: []
|
@@ -91,8 +106,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
106
|
- !ruby/object:Gem::Version
|
92
107
|
version: '0'
|
93
108
|
requirements: []
|
94
|
-
rubygems_version: 3.5.
|
109
|
+
rubygems_version: 3.5.22
|
95
110
|
signing_key:
|
96
111
|
specification_version: 4
|
97
|
-
summary: Build Rails applications entirely
|
112
|
+
summary: Build Rails applications entirely from Phlex, ViewComponents, or any object
|
113
|
+
that responds to `#render_in`
|
98
114
|
test_files: []
|