render_turbo_stream 3.0.5 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +36 -92
- data/app/views/layouts/_add_turbo_frame_tag.html.erb +6 -0
- data/app/views/render_turbo_stream.turbo_stream.erb +13 -4
- data/app/views/render_turbo_stream_request_test.html.erb +13 -5
- data/lib/render_turbo_stream/channel_libs.rb +58 -14
- data/lib/render_turbo_stream/channel_view_helpers.rb +8 -0
- data/lib/render_turbo_stream/check_template.rb +122 -0
- data/lib/render_turbo_stream/controller_channel_helpers.rb +102 -10
- data/lib/render_turbo_stream/controller_helpers.rb +79 -153
- data/lib/render_turbo_stream/controller_libs.rb +162 -0
- data/lib/render_turbo_stream/libs.rb +35 -0
- data/lib/render_turbo_stream/test/request/channel_helpers.rb +50 -10
- data/lib/render_turbo_stream/test/request/helpers.rb +22 -10
- data/lib/render_turbo_stream/test/request/libs.rb +97 -42
- data/lib/render_turbo_stream/version.rb +1 -1
- data/lib/render_turbo_stream.rb +3 -0
- metadata +13 -9
@@ -2,6 +2,7 @@ module RenderTurboStream
|
|
2
2
|
module ControllerChannelHelpers
|
3
3
|
|
4
4
|
def render_to_all(target_id, action = :replace, partial: nil, template: nil, locals: nil)
|
5
|
+
evaluate_instance_variables
|
5
6
|
render_to_channel(
|
6
7
|
'all',
|
7
8
|
target_id,
|
@@ -26,7 +27,7 @@ module RenderTurboStream
|
|
26
27
|
|
27
28
|
render_to_channel(
|
28
29
|
"authenticated-user-#{helpers.current_user.id}",
|
29
|
-
target_id,
|
30
|
+
RenderTurboStream::Libs.target_id_to_target(target_id),
|
30
31
|
action,
|
31
32
|
partial: partial,
|
32
33
|
locals: locals
|
@@ -47,23 +48,25 @@ module RenderTurboStream
|
|
47
48
|
|
48
49
|
render_to_channel(
|
49
50
|
"authenticated-group-#{group}",
|
50
|
-
target_id,
|
51
|
+
RenderTurboStream::Libs.target_id_to_target(target_id),
|
51
52
|
action,
|
52
53
|
partial: partial,
|
53
54
|
locals: locals
|
54
55
|
)
|
55
56
|
end
|
56
57
|
|
57
|
-
def render_to_channel(channel, target_id, action, partial: nil, template: nil, locals: nil)
|
58
|
+
def render_to_channel(channel, target_id, action, partial: nil, template: nil, locals: nil, instance_variables: true)
|
59
|
+
|
60
|
+
raise 'Arguments partial and template cannot both be specified' if partial && template
|
58
61
|
|
59
62
|
disable_default = false
|
60
|
-
if partial
|
61
|
-
|
62
|
-
elsif template.present?
|
63
|
-
|
63
|
+
if partial.present?
|
64
|
+
_partial = RenderTurboStream::Libs.partial_path(nil, target_id, controller_path, partial)
|
65
|
+
elsif template.present?
|
66
|
+
_template = RenderTurboStream::Libs.partial_path(nil, target_id, controller_path, template)
|
64
67
|
disable_default = true
|
65
68
|
else
|
66
|
-
|
69
|
+
_template = [controller_path, action_name].join('/')
|
67
70
|
disable_default = true
|
68
71
|
end
|
69
72
|
|
@@ -73,7 +76,17 @@ module RenderTurboStream
|
|
73
76
|
@render_cable_template_was_called = true
|
74
77
|
end
|
75
78
|
|
76
|
-
|
79
|
+
evaluate_instance_variables
|
80
|
+
|
81
|
+
libs = RenderTurboStream::ChannelLibs.new(response)
|
82
|
+
libs.render_to_channel(
|
83
|
+
channel,
|
84
|
+
RenderTurboStream::Libs.target_id_to_target(target_id),
|
85
|
+
action,
|
86
|
+
self,
|
87
|
+
template: _template,
|
88
|
+
partial: _partial, locals: locals
|
89
|
+
)
|
77
90
|
|
78
91
|
end
|
79
92
|
|
@@ -114,7 +127,86 @@ module RenderTurboStream
|
|
114
127
|
end
|
115
128
|
|
116
129
|
def action_to_channel(channel, command, arguments)
|
117
|
-
RenderTurboStream::ChannelLibs.
|
130
|
+
libs = RenderTurboStream::ChannelLibs.new(response)
|
131
|
+
libs.action_to_channel(channel, command, arguments)
|
132
|
+
end
|
133
|
+
|
134
|
+
def turbo_channel_save(
|
135
|
+
save_action,
|
136
|
+
object: nil, # object used in save_action, example: @customer
|
137
|
+
|
138
|
+
if_success_redirect_to: nil, # does a regular redirect. Works if you are inside a turbo_frame and just want to redirect inside that frame BUT CANNOT STREAM OTHERS ACTIONS ON THE SAME RESPONSE https://github.com/rails/rails/issues/48056
|
139
|
+
|
140
|
+
if_success: nil, # hash for a partial to render or array with actions (as array) or hashes for partials within
|
141
|
+
if_error: nil, # additional partials that should be rendered if save_action failed
|
142
|
+
add: [], # additional streams
|
143
|
+
|
144
|
+
if_success_notices: nil, # array of strings, override default generated flash generation in the case of success
|
145
|
+
if_error_alerts: nil,
|
146
|
+
add_notices: nil, # array of strings
|
147
|
+
add_alerts: nil,
|
148
|
+
|
149
|
+
flash_controller_action_name: action_name, # options: 'update', 'create', otherwise you have to declare a translation in config/locales like "activerecord.success.#{flash_controller_action_name}" and "activerecord.errors.#{flash_controller_action_name}"
|
150
|
+
instance_variables: true # options: if false, nothing happens, if true: Instance variables that matching to controller name like @article or @articles are set to locals. By Array you can add more, example: [:my_var]
|
151
|
+
)
|
152
|
+
|
153
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
154
|
+
# LOGIC
|
155
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
156
|
+
|
157
|
+
unless object
|
158
|
+
object = eval("@#{controller_name.classify.underscore}")
|
159
|
+
end
|
160
|
+
|
161
|
+
libs = RenderTurboStream::ControllerLibs.new(save_action)
|
162
|
+
model_name = object.model_name.human
|
163
|
+
|
164
|
+
turbo_actions = libs.generate_flash(
|
165
|
+
model_name,
|
166
|
+
flash_controller_action_name,
|
167
|
+
if_success_notices,
|
168
|
+
if_error_alerts,
|
169
|
+
add_notices,
|
170
|
+
add_alerts,
|
171
|
+
)[:turbo_actions]
|
172
|
+
|
173
|
+
turbo_actions += libs.additional_actions(
|
174
|
+
if_success,
|
175
|
+
if_error,
|
176
|
+
add
|
177
|
+
)
|
178
|
+
|
179
|
+
if libs.action_errors(turbo_actions).present?
|
180
|
+
raise libs.action_errors(turbo_actions).join(', ')
|
181
|
+
end
|
182
|
+
|
183
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
184
|
+
#== RENDER TO CHANNEL
|
185
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
186
|
+
|
187
|
+
libs = RenderTurboStream::ChannelLibs.new(response)
|
188
|
+
if (helpers.current_user.id rescue false)
|
189
|
+
libs.send_actions_to_channel(
|
190
|
+
"authenticated-user-#{helpers.current_user.id}",
|
191
|
+
turbo_actions,
|
192
|
+
instance_variables: instance_variables
|
193
|
+
)
|
194
|
+
end
|
195
|
+
|
196
|
+
if save_action && if_success_redirect_to.present?
|
197
|
+
response.status = 302
|
198
|
+
redirect_to if_success_redirect_to
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
@render_turbo_stream_evaluate_instance_variables = nil
|
204
|
+
|
205
|
+
def evaluate_instance_variables
|
206
|
+
@render_turbo_stream_evaluate_instance_variables ||= (
|
207
|
+
{ var_test: 'alpha' }
|
208
|
+
)
|
209
|
+
|
118
210
|
end
|
119
211
|
|
120
212
|
end
|
@@ -2,187 +2,118 @@ module RenderTurboStream
|
|
2
2
|
module ControllerHelpers
|
3
3
|
|
4
4
|
# Handles translated flash messages as defined in translations and configs.
|
5
|
-
# If :
|
5
|
+
# If :if_success_redirect_to and channel set up and allow_channel_to_me_for_turbo_stream_save are configured, sends flash message by channel_to_me.
|
6
6
|
# you can add more stream actions to the same response
|
7
7
|
|
8
8
|
def turbo_stream_save(
|
9
9
|
save_action,
|
10
|
-
redirect_on_success_to: nil, # does a regular redirect. Works if you are inside a turbo_frame and just want to redirect inside that frame BUT CANNOT STREAM OTHERS ACTIONS ON THE SAME RESPONSE https://github.com/rails/rails/issues/48056
|
11
|
-
turbo_redirect_on_success_to: nil, # does a full page redirect (break out of all frames by turbo_power redirect)
|
12
10
|
object: nil, # object used in save_action, example: @customer
|
13
|
-
|
14
|
-
|
11
|
+
|
12
|
+
if_success_redirect_to: nil, # does a regular redirect. Works if you are inside a turbo_frame and just want to redirect inside that frame BUT CANNOT STREAM OTHERS ACTIONS ON THE SAME RESPONSE https://github.com/rails/rails/issues/48056
|
13
|
+
if_success_turbo_redirect_to: nil, # does a full page redirect (break out of all frames by turbo_power redirect)
|
14
|
+
|
15
|
+
target_id: nil, # IF NIL: no partial will be rendered AND IF allowed by config: it would send by channel *_to_me and not affect the default response-rendering
|
16
|
+
partial: nil,
|
15
17
|
action: 'replace', # options: append, prepend
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
id: nil,
|
29
|
-
partial: 'form',
|
30
|
-
locals: {},
|
31
|
-
action: 'replace'
|
32
|
-
}
|
33
|
-
], # additional partials that should be rendered if save_action failed
|
34
|
-
add_flash_alerts: [], #=> array of strings
|
35
|
-
add_flash_notices: [], #=> array of strings
|
36
|
-
flashes_on_success: [], #=> array of strings
|
37
|
-
flashes_on_error: [] #=> array of strings
|
18
|
+
locals: {}, # locals used by the target_id
|
19
|
+
|
20
|
+
if_success: nil, # hash for a partial to render or array with actions (as array) or hashes for partials within
|
21
|
+
if_error: nil, # additional partials that should be rendered if save_action failed
|
22
|
+
add: [], # additional streams
|
23
|
+
|
24
|
+
if_success_notices: nil, # array of strings, override default generated flash generation in the case of success
|
25
|
+
if_error_alerts: nil,
|
26
|
+
add_notices: nil, # array of strings
|
27
|
+
add_alerts: nil,
|
28
|
+
|
29
|
+
flash_controller_action_name: action_name # options: 'update', 'create', otherwise you have to declare a translation in config/locales like "activerecord.success.#{flash_controller_action_name}" and "activerecord.errors.#{flash_controller_action_name}"
|
38
30
|
)
|
39
31
|
|
32
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
33
|
+
# EXCEPTIONS
|
34
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
35
|
+
|
36
|
+
raise 'render_turbo_stream: arguments target_id and if_success_redirect_to cannot be provided both' if target_id && if_success_redirect_to
|
37
|
+
|
38
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
39
|
+
# LOGIC
|
40
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
41
|
+
|
40
42
|
unless object
|
41
43
|
object = eval("@#{controller_name.classify.underscore}")
|
42
44
|
end
|
43
45
|
|
44
|
-
|
46
|
+
libs = RenderTurboStream::ControllerLibs.new(save_action)
|
47
|
+
model_name = object.model_name.human
|
45
48
|
|
46
|
-
streams = (
|
49
|
+
streams = (target_id ? libs.generate_action(controller_path, target_id, action, partial, locals) : [])
|
50
|
+
|
51
|
+
flashes = libs.generate_flash(
|
52
|
+
model_name,
|
53
|
+
flash_controller_action_name,
|
54
|
+
if_success_notices,
|
55
|
+
if_error_alerts,
|
56
|
+
add_notices,
|
57
|
+
add_alerts,
|
58
|
+
)
|
59
|
+
streams += flashes[:turbo_actions]
|
60
|
+
|
61
|
+
streams += libs.additional_actions(
|
62
|
+
if_success,
|
63
|
+
if_error,
|
64
|
+
add
|
65
|
+
)
|
47
66
|
|
48
|
-
if
|
49
|
-
|
50
|
-
streams_on_success.each do |s|
|
51
|
-
if s.is_a?(Array)
|
52
|
-
streams.push(s)
|
53
|
-
elsif s.is_a?(Hash) && s[:id].present?
|
54
|
-
streams.push(s)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
else
|
58
|
-
response.status = :unprocessable_entity
|
59
|
-
streams += streams_on_error.select { |s| s[:id].present? }
|
67
|
+
if libs.action_errors(streams).present?
|
68
|
+
raise libs.action_errors(streams).join(', ')
|
60
69
|
end
|
61
70
|
|
62
|
-
|
63
|
-
|
64
|
-
model_name = object.model_name.human
|
65
|
-
if save_action
|
66
|
-
flash_notices = if flashes_on_success.present?
|
67
|
-
flashes_on_success
|
68
|
-
elsif flash_action.to_s == 'create'
|
69
|
-
str = I18n.t(
|
70
|
-
'activerecord.success.successfully_created',
|
71
|
-
default: '%<model_name>s successfully created'
|
72
|
-
)
|
73
|
-
[format(str, model_name: model_name)]
|
74
|
-
elsif flash_action.to_s == 'update'
|
75
|
-
str = I18n.t(
|
76
|
-
'activerecord.success.successfully_updated',
|
77
|
-
default: '%<model_name>s successfully updated'
|
78
|
-
)
|
79
|
-
[format(str, model_name: model_name)]
|
80
|
-
else
|
81
|
-
str = I18n.t(
|
82
|
-
"activerecord.success.#{flash_action}",
|
83
|
-
default: '%<model_name>s successfully updated'
|
84
|
-
)
|
85
|
-
[format(str, model_name: model_name)]
|
86
|
-
end
|
87
|
-
flash_alerts = []
|
88
|
-
else
|
89
|
-
flash_alerts = if flashes_on_error.present?
|
90
|
-
flashes_on_error
|
91
|
-
elsif flash_action.to_s == 'create'
|
92
|
-
str = I18n.t(
|
93
|
-
'activerecord.errors.messages.could_not_create',
|
94
|
-
default: '%<model_name>s could not be created'
|
95
|
-
)
|
96
|
-
[format(str, model_name: model_name)]
|
97
|
-
elsif flash_action.to_s == 'update'
|
98
|
-
str = I18n.t(
|
99
|
-
'activerecord.errors.messages.could_not_update',
|
100
|
-
default: '%<model_name>s could not be updated'
|
101
|
-
)
|
102
|
-
[format(str, model_name: model_name)]
|
103
|
-
else
|
104
|
-
str = I18n.t(
|
105
|
-
"activerecord.errors.messages.#{flash_action}",
|
106
|
-
default: '%<model_name>s could not be updated'
|
107
|
-
)
|
108
|
-
[format(str, model_name: model_name)]
|
109
|
-
end
|
110
|
-
flash_notices = []
|
71
|
+
unless save_action
|
72
|
+
response.status = 422
|
111
73
|
end
|
112
74
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
flash_id = (_flash_id ? _flash_id : "ERROR, MISSING CONFIG => config.x.render_turbo_stream.flash_id")
|
117
|
-
flash_partial = Rails.configuration.x.render_turbo_stream.flash_partial
|
118
|
-
flash_action = Rails.configuration.x.render_turbo_stream.flash_action
|
119
|
-
flash_notices.each do |notice|
|
120
|
-
next unless notice.present?
|
121
|
-
# inside the flash partial has to be a loop that handles all theese flashes
|
122
|
-
flash_stream = {
|
123
|
-
id: flash_id,
|
124
|
-
partial: flash_partial,
|
125
|
-
action: flash_action,
|
126
|
-
locals: { success: true, message: notice }
|
127
|
-
}
|
128
|
-
streams.push(flash_stream)
|
129
|
-
end
|
130
|
-
flash_alerts.each do |alert|
|
131
|
-
next unless alert.present?
|
132
|
-
# inside the flash partial has to be a loop that handles all theese flashes
|
133
|
-
flash_stream = {
|
134
|
-
id: flash_id,
|
135
|
-
partial: flash_partial,
|
136
|
-
action: flash_action,
|
137
|
-
locals: { success: false, message: alert }
|
138
|
-
}
|
139
|
-
streams.push(flash_stream)
|
140
|
-
end
|
75
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
76
|
+
#== RENDER TO STREAM
|
77
|
+
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
141
78
|
|
142
|
-
|
79
|
+
allow_channel = (Rails.configuration.x.render_turbo_stream.allow_channel_to_me_for_turbo_stream_save rescue false) && (helpers.current_user.id.present? rescue false)
|
143
80
|
|
144
|
-
if save_action &&
|
81
|
+
if save_action && if_success_turbo_redirect_to.present?
|
145
82
|
response.status = 302
|
146
|
-
flash[:alert] =
|
147
|
-
flash[:notice] =
|
148
|
-
Rails.logger.debug(" • Set flash[:alert] => #{
|
149
|
-
Rails.logger.debug(" • Set flash[:notice] => #{
|
83
|
+
flash[:alert] = flashes[:alerts]
|
84
|
+
flash[:notice] = flashes[:notices]
|
85
|
+
Rails.logger.debug(" • Set flash[:alert] => #{flashes[:alerts]}") if flashes[:alerts].present?
|
86
|
+
Rails.logger.debug(" • Set flash[:notice] => #{flashes[:notices]}") if flashes[:notices].present?
|
150
87
|
render_turbo_stream([
|
151
88
|
[
|
152
89
|
:redirect_to,
|
153
|
-
|
90
|
+
if_success_turbo_redirect_to
|
154
91
|
]
|
155
92
|
])
|
156
|
-
elsif save_action &&
|
93
|
+
elsif save_action && if_success_redirect_to.present?
|
157
94
|
response.status = 302
|
158
|
-
if
|
159
|
-
streams.
|
160
|
-
|
161
|
-
|
162
|
-
render_to_me(
|
163
|
-
s[:id],
|
164
|
-
flash_action,
|
165
|
-
partial: s[:partial],
|
166
|
-
locals: s[:locals]
|
167
|
-
)
|
168
|
-
end
|
169
|
-
|
95
|
+
if allow_channel
|
96
|
+
Rails.logger.debug(" • Sent #{streams.length} actions through Turbo::StreamsChannel to enable defined redirection because allowed in configs.")
|
97
|
+
c_libs = RenderTurboStream::ChannelLibs.new(response)
|
98
|
+
c_libs.send_actions_to_channel("authenticated-user-#{helpers.current_user.id}", streams, @render_turbo_stream_evaluate_instance_variables)
|
170
99
|
else
|
171
100
|
flash[:alert] = flash_alerts
|
172
101
|
flash[:notice] = flash_notices
|
173
102
|
Rails.logger.debug(" • Set flash[:alert] => #{flash_alerts}") if flash_alerts.present?
|
174
103
|
Rails.logger.debug(" • Set flash[:notice] => #{flash_notices}") if flash_notices.present?
|
175
104
|
end
|
176
|
-
redirect_to
|
105
|
+
redirect_to if_success_redirect_to
|
106
|
+
|
107
|
+
elsif !target_id.present? && allow_channel
|
108
|
+
Rails.logger.debug(" • Sent #{streams.length} actions through Turbo::StreamsChannel because no target_id defined and allowed in configs.")
|
109
|
+
c_libs = RenderTurboStream::ChannelLibs.new(response)
|
110
|
+
c_libs.send_actions_to_channel("authenticated-user-#{helpers.current_user.id}", streams, @render_turbo_stream_evaluate_instance_variables)
|
177
111
|
|
178
112
|
else
|
179
|
-
flash.now[:alert] = flash_alerts
|
180
|
-
flash.now[:notice] = flash_notices
|
181
113
|
render_turbo_stream(streams)
|
182
114
|
end
|
183
115
|
end
|
184
116
|
|
185
|
-
|
186
117
|
# renders a array of partials to send by turbo-stream and / or actions like turbo_power gem includes, to turbo_stream
|
187
118
|
def render_turbo_stream(array)
|
188
119
|
|
@@ -192,12 +123,12 @@ module RenderTurboStream
|
|
192
123
|
Rails.logger.warn " WARNING render_turbo_stream: Empty element inside attributes: «#{array}»"
|
193
124
|
elsif pr.is_a?(Hash)
|
194
125
|
props = pr.symbolize_keys
|
195
|
-
raise "missing attribute :id in #{props}" if !props[:id].present?
|
196
|
-
part = (props[:partial].present? ? props[:partial] : props[:id]).gsub('-', '_')
|
197
|
-
partial = (part.to_s.include?('/') ? part : [controller_path, part].join('/'))
|
198
126
|
r = props
|
127
|
+
r[:target] = RenderTurboStream::Libs.target_id_to_target(props[:target_id]) if props[:target_id].present?
|
128
|
+
raise "Missing attribute :target in #{props}" if !props[:target].present?
|
129
|
+
r.delete(:target_id)
|
199
130
|
r[:action] = (props[:action].present? ? props[:action] : :replace)
|
200
|
-
r[:partial] = partial
|
131
|
+
r[:partial] = RenderTurboStream::Libs.partial_path(props[:target], props[:target_id], controller_path, props[:partial])
|
201
132
|
r[:type] = 'stream-partial'
|
202
133
|
ary.push(r)
|
203
134
|
elsif pr.is_a?(Array)
|
@@ -219,16 +150,11 @@ module RenderTurboStream
|
|
219
150
|
|
220
151
|
# renders a partial to turbo_stream
|
221
152
|
|
222
|
-
def stream_partial(
|
223
|
-
id,
|
224
|
-
partial: nil, #=> default: id
|
225
|
-
action: :replace,
|
226
|
-
locals: {}
|
227
|
-
)
|
153
|
+
def stream_partial( target_id, partial: nil, action: :replace, locals: {} )
|
228
154
|
render_turbo_stream(
|
229
155
|
[
|
230
156
|
{
|
231
|
-
|
157
|
+
target: RenderTurboStream::Libs.target_id_to_target(target_id),
|
232
158
|
partial: partial,
|
233
159
|
action: action,
|
234
160
|
locals: locals
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module RenderTurboStream
|
2
|
+
class ControllerLibs
|
3
|
+
|
4
|
+
def initialize(save_action)
|
5
|
+
@save_action = save_action
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate_flash( model_name, controller_action, if_success_notices, if_error_alerts, add_notices, add_alerts )
|
9
|
+
|
10
|
+
target_id = (Rails.configuration.x.render_turbo_stream.flash_target_id rescue nil)
|
11
|
+
raise "Missing configuration: config.x.render_turbo_stream.flash_target_id" unless target_id
|
12
|
+
partial = Rails.configuration.x.render_turbo_stream.flash_partial
|
13
|
+
raise "Missing configuration: configuration.x.render_turbo_stream.flash_partial" unless partial
|
14
|
+
turbo_action = Rails.configuration.x.render_turbo_stream.flash_turbo_action
|
15
|
+
raise "Missing configuration: configuration.x.render_turbo_stream.flash_turbo_action" unless turbo_action
|
16
|
+
|
17
|
+
|
18
|
+
if @save_action
|
19
|
+
notices = if if_success_notices
|
20
|
+
if_success_notices
|
21
|
+
elsif controller_action.to_sym == :create
|
22
|
+
str = I18n.t(
|
23
|
+
'activerecord.success.successfully_created',
|
24
|
+
default: '%<model_name>s successfully created'
|
25
|
+
)
|
26
|
+
[format(str, model_name: model_name)]
|
27
|
+
elsif controller_action.to_sym == :update
|
28
|
+
str = I18n.t(
|
29
|
+
'activerecord.success.successfully_updated',
|
30
|
+
default: '%<model_name>s successfully updated'
|
31
|
+
)
|
32
|
+
[format(str, model_name: model_name)]
|
33
|
+
else
|
34
|
+
str = I18n.t(
|
35
|
+
"activerecord.success.#{controller_action}",
|
36
|
+
default: '%<model_name>s successfully updated'
|
37
|
+
)
|
38
|
+
[format(str, model_name: model_name)]
|
39
|
+
end
|
40
|
+
alerts = []
|
41
|
+
else
|
42
|
+
alerts = if if_error_alerts
|
43
|
+
if_error_alerts
|
44
|
+
elsif controller_action.to_sym == :create
|
45
|
+
str = I18n.t(
|
46
|
+
'activerecord.errors.messages.could_not_create',
|
47
|
+
default: '%<model_name>s could not be created'
|
48
|
+
)
|
49
|
+
[format(str, model_name: model_name)]
|
50
|
+
elsif controller_action.to_sym == :update
|
51
|
+
str = I18n.t(
|
52
|
+
'activerecord.errors.messages.could_not_update',
|
53
|
+
default: '%<model_name>s could not be updated'
|
54
|
+
)
|
55
|
+
[format(str, model_name: model_name)]
|
56
|
+
else
|
57
|
+
str = I18n.t(
|
58
|
+
"activerecord.errors.messages.#{controller_action}",
|
59
|
+
default: '%<model_name>s could not be updated'
|
60
|
+
)
|
61
|
+
[format(str, model_name: model_name)]
|
62
|
+
end
|
63
|
+
notices = []
|
64
|
+
end
|
65
|
+
|
66
|
+
turbo_actions = []
|
67
|
+
notices += add_notices.to_a
|
68
|
+
alerts += add_alerts.to_a
|
69
|
+
notices.each do |notice|
|
70
|
+
next unless notice.present?
|
71
|
+
flash_stream = {
|
72
|
+
target: RenderTurboStream::Libs.target_id_to_target(target_id),
|
73
|
+
partial: partial,
|
74
|
+
action: turbo_action,
|
75
|
+
locals: { success: true, message: notice }
|
76
|
+
}
|
77
|
+
turbo_actions.push(flash_stream)
|
78
|
+
end
|
79
|
+
alerts.each do |alert|
|
80
|
+
next unless alert.present?
|
81
|
+
flash_stream = {
|
82
|
+
target: RenderTurboStream::Libs.target_id_to_target(target_id),
|
83
|
+
partial: partial,
|
84
|
+
action: turbo_action,
|
85
|
+
locals: { success: false, message: alert }
|
86
|
+
}
|
87
|
+
turbo_actions.push(flash_stream)
|
88
|
+
end
|
89
|
+
{ turbo_actions: turbo_actions, alerts: alerts, notices: notices }
|
90
|
+
end
|
91
|
+
|
92
|
+
def additional_actions( if_success, if_error, add )
|
93
|
+
|
94
|
+
(@save_action ? make_actions(if_success) : make_actions(if_error)) + make_actions(add)
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
def generate_action( controller_path, target_id, action, partial, locals )
|
99
|
+
libs = RenderTurboStream::Libs
|
100
|
+
target = libs.target_id_to_target(target_id)
|
101
|
+
_partial = libs.partial_path(nil, target_id, controller_path, partial)
|
102
|
+
[target: target, partial: _partial, locals: locals, action: action]
|
103
|
+
end
|
104
|
+
|
105
|
+
def action_errors(actions)
|
106
|
+
r = []
|
107
|
+
actions.each do |a|
|
108
|
+
if a.is_a?(Hash)
|
109
|
+
unless a[:target].present?
|
110
|
+
r.push("Missing attribute :target for => «#{a}»")
|
111
|
+
end
|
112
|
+
unless a[:partial].present?
|
113
|
+
r.push("Missing attribute :partial for => «#{a}»")
|
114
|
+
end
|
115
|
+
unless a[:action].present?
|
116
|
+
r.push("Missing attribute :action for => «#{a}»")
|
117
|
+
end
|
118
|
+
elsif a.is_a?(Array)
|
119
|
+
unless a.first.is_a?(String) || a.first.is_a?(Symbol)
|
120
|
+
r.push("Assuming a command, but the first attribute must be a string or symbol => «#{a}»")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
r
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
# streamline actions to array
|
130
|
+
# valid inputs for if_success or if_error or add
|
131
|
+
# [:add_css_class, ...]
|
132
|
+
# [[:add_css_class, ..], ..]
|
133
|
+
# {target_id: '..', ..}
|
134
|
+
# [{target_id: '..', ..}, ..]
|
135
|
+
|
136
|
+
def make_actions(actions)
|
137
|
+
res = if actions.present?
|
138
|
+
if actions.is_a?(Hash)
|
139
|
+
[actions]
|
140
|
+
elsif actions.is_a?(Array)
|
141
|
+
if actions.first.is_a?(String) || actions.first.is_a?(Symbol)
|
142
|
+
[actions]
|
143
|
+
else
|
144
|
+
actions
|
145
|
+
end
|
146
|
+
end
|
147
|
+
else
|
148
|
+
[]
|
149
|
+
end
|
150
|
+
res.map do |a|
|
151
|
+
if a.is_a?(Hash) && a.key?(:target_id)
|
152
|
+
a = a.merge(target: "##{a[:target_id]}")
|
153
|
+
a.delete(:target_id)
|
154
|
+
a
|
155
|
+
else
|
156
|
+
a
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RenderTurboStream
|
2
|
+
class Libs
|
3
|
+
|
4
|
+
def self.target_id_to_target(target_id)
|
5
|
+
if target_id.present?
|
6
|
+
"##{target_id}"
|
7
|
+
else
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.target_to_target_id(target)
|
13
|
+
if target.present? && target.to_s[0] == '#'
|
14
|
+
target[1..-1]
|
15
|
+
else
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.partial_path(target, target_id, controller_path, partial)
|
21
|
+
if partial && partial.to_s.include?('/')
|
22
|
+
partial
|
23
|
+
elsif partial.present?
|
24
|
+
[controller_path, partial].join('/')
|
25
|
+
elsif target_id.present?
|
26
|
+
[controller_path, target_id.gsub('-', '_')].join('/')
|
27
|
+
elsif target.present?
|
28
|
+
[controller_path, RenderTurboStream::Libs.target_to_target_id(target).gsub('-', '_')].join('/')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|