render_turbo_stream 0.1.9 → 0.1.11
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/README.md +56 -16
- data/app/controllers/render_turbo_stream/application_controller.rb +4 -0
- data/app/views/render_turbo_stream_partials.turbo_stream.erb +52 -0
- data/app/views/render_turbo_stream_redirect.turbo_stream.erb +1 -0
- data/lib/render_turbo_stream/engine.rb +5 -0
- data/lib/render_turbo_stream/version.rb +1 -1
- data/lib/render_turbo_stream.rb +155 -5
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbc78913dcbad95c4f8de2b0188ab6eff2db1ac2390590a491427af071f2fa55
|
4
|
+
data.tar.gz: c2d381f27a631862490811f5c140f91245370ad3b1b82e3ba41771707adae732
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5873014fd22b2b1d4d2ded650f37bdc5f6e865ada01608c82ad2c891199c1e342bb6e7a4d94319c6e92c0cfea196fb19230cdebc931915fb2b2e420cc3ab1653
|
7
|
+
data.tar.gz: 854105573f8b7a5b8f34ac031d93c4e0a01eb2f5b4263a1495cfac17d53a391431c0ec5a339a5666e4ec8340d029218c2914501fba1a65869508185661d0eab9
|
data/README.md
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# RenderTurboStream
|
2
2
|
|
3
|
-
|
3
|
+
The machine gun for your turbo-stream partials.
|
4
4
|
|
5
|
-
|
5
|
+
Creating a gem from this is in work, see [rails issue](https://github.com/rails/rails/issues/47954)
|
6
6
|
|
7
|
-
|
7
|
+
Defining templates like `update.turbo_stream.haml` annoyed me.
|
8
8
|
|
9
|
-
|
9
|
+
Working consistently by turbo_stream means: shooting many partials to the frontend which always needs the same attributes: ID, partial and maybe some locals. This gem serializes that: Partials can be steered directly from the controller.
|
10
10
|
|
11
|
-
|
11
|
+
Currently it is only possible by copy and paste the code, see below.
|
12
12
|
|
13
13
|
## Installation
|
14
14
|
|
@@ -24,36 +24,74 @@ The corresponding partials for flashes could look [like this](https://gitlab.com
|
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
+
`turbo_stream_save` is a special method for streamline `update` or `create` functions for `turbo_stream`, which could look like so:
|
28
|
+
|
27
29
|
```ruby
|
28
30
|
def create
|
29
31
|
@customer = Customer.new(customer_params)
|
30
32
|
|
31
|
-
|
33
|
+
turbo_stream_save(
|
32
34
|
@customer.save,
|
33
|
-
redirect_on_success_to: edit_customer_path(@customer)
|
34
|
-
id: 'customer-form-wrapper',
|
35
|
-
partial: 'customer_form',
|
35
|
+
redirect_on_success_to: edit_customer_path(@customer)
|
36
36
|
)
|
37
37
|
|
38
38
|
end
|
39
39
|
```
|
40
40
|
|
41
|
-
and
|
41
|
+
This sets a status, generates a flash message and performs `stream_partials`, which could result like that:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
stream_partials(
|
45
|
+
[
|
46
|
+
{
|
47
|
+
id: 'form',
|
48
|
+
partial: 'form'
|
49
|
+
},
|
50
|
+
{
|
51
|
+
id: 'flash-wrapper',
|
52
|
+
partial: 'layouts/flashes',
|
53
|
+
action: :prepend
|
54
|
+
}
|
55
|
+
]
|
56
|
+
)
|
57
|
+
```
|
42
58
|
|
43
|
-
|
59
|
+
The `stream_partial` method is nothing else than a singular of `stream_partials`
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
stream_partial(
|
63
|
+
id,
|
64
|
+
partial: nil, #=> default: id.gsub('-','_')
|
65
|
+
locals: {},
|
66
|
+
action: nil #=> default: :replace
|
67
|
+
)
|
68
|
+
```
|
44
69
|
|
45
70
|
## Testing
|
46
71
|
|
47
|
-
|
72
|
+
For system testing you need capybara.
|
48
73
|
|
49
|
-
|
74
|
+
For enabling request specs:
|
75
|
+
If `request.format` is not `turbo_stream` the method responds as `json` with status:
|
50
76
|
|
51
77
|
Success and redirection: `302`
|
52
|
-
|
53
78
|
Success without redirection: `200`
|
54
|
-
|
55
79
|
Save Action failed: `422` `:unprocessable_entity`
|
56
80
|
|
81
|
+
Testing the `response.body` by rspec could look like this:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
it 'update failed' do
|
85
|
+
a = FactoryBot.create(:article)
|
86
|
+
patch article_path(a, params: invalid_params)
|
87
|
+
expect(response.status).to eq(422)
|
88
|
+
h = JSON.parse(response.body)
|
89
|
+
expect(h['form']['partial']).to eq('articles/form')
|
90
|
+
expect(h['flash-box']['partial']).to eq('layouts/flash')
|
91
|
+
expect(h.keys.length).to eq(2)
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
57
95
|
## Parameters
|
58
96
|
|
59
97
|
`save_action` (first parameter, boolean) true if successful
|
@@ -84,7 +122,7 @@ Save Action failed: `422` `:unprocessable_entity`
|
|
84
122
|
|
85
123
|
gem `turbo_power` (is included, used for redirection)
|
86
124
|
|
87
|
-
**Translations
|
125
|
+
**Translations**
|
88
126
|
|
89
127
|
`activerecord.success.successfully_created`
|
90
128
|
|
@@ -94,6 +132,8 @@ gem `turbo_power` (is included, used for redirection)
|
|
94
132
|
|
95
133
|
`activerecord.errors.messages.could_not_update`
|
96
134
|
|
135
|
+
example value: `"%<model_name>s successfully created"`
|
136
|
+
|
97
137
|
.. and Model Name Translations
|
98
138
|
|
99
139
|
**Flash configuration**
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<% error = false %>
|
2
|
+
<% control = [] %>
|
3
|
+
<% local_assigns[:streams].each do |s| %>
|
4
|
+
<% ctl = { partial: s[:partial], id: s[:id] } %>
|
5
|
+
<% info = { id: s[:id], partial: s[:partial], locals: s[:locals] } %>
|
6
|
+
|
7
|
+
<% if !s[:id] %>
|
8
|
+
<% Rails.logger.error(" ERROR RENDER TURBO STREAM => MISSING ID => #{s}") %>
|
9
|
+
<% error = true %>
|
10
|
+
|
11
|
+
<% elsif !s[:partial].present? %>
|
12
|
+
<% Rails.logger.error(" ERROR RENDER TURBO STREAM => MISSING PARTIAL => #{s}") %>
|
13
|
+
<% error = true %>
|
14
|
+
<% ctl[:partial] = nil %>
|
15
|
+
|
16
|
+
<% elsif s[:action].to_sym == :replace %>
|
17
|
+
<% ctl[:action] = :replace %>
|
18
|
+
<% Rails.logger.debug(" • render-turbo-stream REPLACE => #{info}") %>
|
19
|
+
<%= turbo_stream.replace s[:id] do %>
|
20
|
+
<%= render s[:partial], locals: s[:locals] %>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<% elsif s[:action].to_sym == :prepend %>
|
24
|
+
<% ctl[:action] = :prepend %>
|
25
|
+
<% Rails.logger.debug(" • render-turbo-stream PREPEND => #{info}") %>
|
26
|
+
<%= turbo_stream.prepend s[:id] do %>
|
27
|
+
<%= render s[:partial], locals: s[:locals] %>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<% elsif s[:action].to_sym == :append %>
|
31
|
+
<% ctl[:action] = :append %>
|
32
|
+
<% Rails.logger.debug(" • render-turbo-stream APPEND => #{info}") %>
|
33
|
+
<%= turbo_stream.prepend s[:id] do %>
|
34
|
+
<%= render s[:partial], locals: s[:locals] %>
|
35
|
+
<% end %>
|
36
|
+
|
37
|
+
<% else %>
|
38
|
+
<% ctl[:action] = :UNKNOWN %>
|
39
|
+
<% Rails.logger.fatal(" ERROR render-turbo-stream => UNKNOWN ACTION => #{s}") %>
|
40
|
+
<% error = true %>
|
41
|
+
<% end %>
|
42
|
+
|
43
|
+
<% control.push(ctl) %>
|
44
|
+
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<% if error %>
|
48
|
+
<% Rails.logger.error(" RENDER TURBO STREAM HAD ERRORS, REPEATING WHOLE ARRAY: ") %>
|
49
|
+
<% control.each do |c| %>
|
50
|
+
<% Rails.logger.error(" #{c}") %>
|
51
|
+
<% end %>
|
52
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= turbo_stream.redirect_to local_assigns[:url] %>
|
data/lib/render_turbo_stream.rb
CHANGED
@@ -1,12 +1,162 @@
|
|
1
1
|
require "render_turbo_stream/version"
|
2
2
|
require "render_turbo_stream/railtie"
|
3
|
+
require 'render_turbo_stream/engine'
|
3
4
|
|
4
5
|
module RenderTurboStream
|
5
|
-
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
|
7
|
+
def turbo_stream_save(
|
8
|
+
save_action,
|
9
|
+
redirect_on_success_to: nil,
|
10
|
+
object: nil,
|
11
|
+
id: 'form', # if nil: no partial is rendered
|
12
|
+
partial: nil, # default: same like ID
|
13
|
+
action: 'replace',
|
14
|
+
locals: {},
|
15
|
+
streams_on_success: [
|
16
|
+
{
|
17
|
+
id: nil,
|
18
|
+
partial: 'form',
|
19
|
+
locals: {},
|
20
|
+
action: 'replace'
|
21
|
+
}
|
22
|
+
],
|
23
|
+
streams_on_error: [
|
24
|
+
{
|
25
|
+
id: nil,
|
26
|
+
partial: 'form',
|
27
|
+
locals: {},
|
28
|
+
action: 'replace'
|
29
|
+
}
|
30
|
+
],
|
31
|
+
add_flash_alerts: [], #=> array of strings
|
32
|
+
add_flash_notices: [], #=> array of strings
|
33
|
+
flashes_on_success: [], #=> array of strings
|
34
|
+
flashes_on_error: [] #=> array of strings
|
35
|
+
)
|
36
|
+
|
37
|
+
unless object
|
38
|
+
object = eval("@#{controller_name.classify.underscore}")
|
39
|
+
end
|
40
|
+
|
41
|
+
#== Streams / Partials
|
42
|
+
|
43
|
+
streams = [(id ? { id: id, partial: partial, locals: locals, action: action } : nil)]
|
44
|
+
|
45
|
+
if save_action
|
46
|
+
response.status = 200
|
47
|
+
streams += streams_on_success.select { |s| s[:id].present? }
|
48
|
+
else
|
49
|
+
response.status = :unprocessable_entity
|
50
|
+
streams += streams_on_error.select { |s| s[:id].present? }
|
51
|
+
end
|
52
|
+
|
53
|
+
#== FLASHES
|
54
|
+
|
55
|
+
model_name = object.model_name.human
|
56
|
+
if save_action
|
57
|
+
flash_notices = if flashes_on_success.present?
|
58
|
+
flashes_on_success
|
59
|
+
elsif action_name == 'create'
|
60
|
+
[format(I18n.t('activerecord.success.successfully_created'), model_name: model_name)]
|
61
|
+
elsif action_name == 'update'
|
62
|
+
[format(I18n.t('activerecord.success.successfully_updated'), model_name: model_name)]
|
63
|
+
end
|
64
|
+
flash_alerts = []
|
65
|
+
else
|
66
|
+
flash_alerts = if flashes_on_error.present?
|
67
|
+
flashes_on_error
|
68
|
+
elsif action_name == 'create'
|
69
|
+
[format(I18n.t('activerecord.errors.messages.could_not_create'), model_name: model_name)]
|
70
|
+
elsif action_name == 'update'
|
71
|
+
[format(I18n.t('activerecord.errors.messages.could_not_update'), model_name: model_name)]
|
72
|
+
end
|
73
|
+
flash_notices = []
|
74
|
+
end
|
75
|
+
flash_notices += add_flash_notices
|
76
|
+
flash_alerts += add_flash_alerts
|
77
|
+
_flash_id = Rails.configuration.x.render_turbo_stream.flash_id
|
78
|
+
flash_id = (_flash_id ? _flash_id : "ERROR, MISSING CONFIG => config.x.render_turbo_stream.flash_id")
|
79
|
+
flash_partial = Rails.configuration.x.render_turbo_stream.flash_partial
|
80
|
+
flash_action = Rails.configuration.x.render_turbo_stream.flash_action
|
81
|
+
flash_notices.each do |notice|
|
82
|
+
# inside the flash partial has to be a loop that handles all theese flashes
|
83
|
+
flash_stream = {
|
84
|
+
id: flash_id,
|
85
|
+
partial: flash_partial,
|
86
|
+
action: flash_action,
|
87
|
+
locals: { success: true, message: notice }
|
88
|
+
}
|
89
|
+
streams.push(flash_stream)
|
90
|
+
end
|
91
|
+
flash_alerts.each do |alert|
|
92
|
+
# inside the flash partial has to be a loop that handles all theese flashes
|
93
|
+
flash_stream = {
|
94
|
+
id: flash_id,
|
95
|
+
partial: flash_partial,
|
96
|
+
action: flash_action,
|
97
|
+
locals: { success: false, message: alert }
|
98
|
+
}
|
99
|
+
streams.push(flash_stream)
|
10
100
|
end
|
101
|
+
|
102
|
+
#== render
|
103
|
+
|
104
|
+
if save_action && redirect_on_success_to.present?
|
105
|
+
response.status = 302
|
106
|
+
flash[:alert] = flash_alerts
|
107
|
+
flash[:notice] = flash_notices
|
108
|
+
if request.format.to_sym == :turbo_stream
|
109
|
+
render template: 'render_turbo_stream_redirect', locals: { url: redirect_on_success_to }, layout: false
|
110
|
+
else
|
111
|
+
render json: { redirected_to: redirect_on_success_to }
|
112
|
+
end
|
113
|
+
else
|
114
|
+
flash.now[:alert] = flash_alerts
|
115
|
+
flash.now[:notice] = flash_notices
|
116
|
+
stream_partials(streams)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def stream_partials(array)
|
121
|
+
|
122
|
+
ary = []
|
123
|
+
array.dup.each do |props|
|
124
|
+
part = (props[:partial].present? ? props[:partial] : props[:id]).gsub('-', '_')
|
125
|
+
partial = (part.to_s.include?('/') ? part : [controller_path, part].join('/'))
|
126
|
+
r = props
|
127
|
+
r[:action] = (props[:action].present? ? props[:action] : :replace)
|
128
|
+
r[:partial] = partial
|
129
|
+
ary.push(r)
|
130
|
+
end
|
131
|
+
|
132
|
+
if request.format.to_sym == :turbo_stream
|
133
|
+
render template: 'render_turbo_stream_partials', locals: { streams: ary }, layout: false
|
134
|
+
else
|
135
|
+
check = {}
|
136
|
+
ary.each do |a|
|
137
|
+
b = a.dup
|
138
|
+
b.delete(:id)
|
139
|
+
check[a[:id]] = b
|
140
|
+
end
|
141
|
+
render json: check
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def stream_partial(
|
146
|
+
id,
|
147
|
+
partial: nil, #=> default: id
|
148
|
+
action: :replace,
|
149
|
+
locals: {}
|
150
|
+
)
|
151
|
+
stream_partials(
|
152
|
+
[
|
153
|
+
{
|
154
|
+
id: id,
|
155
|
+
partial: partial,
|
156
|
+
action: action,
|
157
|
+
locals: locals
|
158
|
+
}
|
159
|
+
]
|
160
|
+
)
|
11
161
|
end
|
12
162
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: render_turbo_stream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- christian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 7.0.4.3
|
27
|
-
description:
|
27
|
+
description: Coming soon
|
28
28
|
email:
|
29
29
|
- christian@sedlmair.ch
|
30
30
|
executables: []
|
@@ -33,7 +33,11 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- README.md
|
35
35
|
- Rakefile
|
36
|
+
- app/controllers/render_turbo_stream/application_controller.rb
|
37
|
+
- app/views/render_turbo_stream_partials.turbo_stream.erb
|
38
|
+
- app/views/render_turbo_stream_redirect.turbo_stream.erb
|
36
39
|
- lib/render_turbo_stream.rb
|
40
|
+
- lib/render_turbo_stream/engine.rb
|
37
41
|
- lib/render_turbo_stream/railtie.rb
|
38
42
|
- lib/render_turbo_stream/version.rb
|
39
43
|
- lib/tasks/render_turbo_stream_tasks.rake
|
@@ -62,5 +66,5 @@ requirements: []
|
|
62
66
|
rubygems_version: 3.4.12
|
63
67
|
signing_key:
|
64
68
|
specification_version: 4
|
65
|
-
summary:
|
69
|
+
summary: Coming soon
|
66
70
|
test_files: []
|