render_turbo_stream 3.0.5 → 4.0.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.
@@ -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
- template = nil
62
- elsif template.present? && !template.to_s.include?('/')
63
- template = [controller_path, template].join('/')
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
- template = [controller_path, action_name].join('/')
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
- RenderTurboStream::ChannelLibs.render_to_channel(response, channel, target_id, action, template: template, partial: partial, locals: locals)
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.action_to_channel(response, channel, command, arguments)
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 :redirect_on_success_to and channel set up and allow_channel_for_turbo_stream_save are configured, sends flash message by channel_to_me.
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
- id: nil, # if nil: no partial is rendered
14
- partial: nil, # example: 'customers/form' default: "#{controller_path}/#{id}"
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
- flash_action: action_name, # options: 'update', 'create', otherwise you have to declare a translation in config/locales like "activerecord.success.#{flash_action}" and "activerecord.errors.#{flash_action}"
17
- locals: {}, # locals used by the partial
18
- streams_on_success: [
19
- {
20
- id: nil,
21
- partial: 'form',
22
- locals: {},
23
- action: 'replace'
24
- }
25
- ], # additional partials that should be rendered if save_action succeeded
26
- streams_on_error: [
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
- #== Streams / Partials
46
+ libs = RenderTurboStream::ControllerLibs.new(save_action)
47
+ model_name = object.model_name.human
45
48
 
46
- streams = (id ? [id: id, partial: partial, locals: locals, action: action] : [])
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 save_action
49
- response.status = 200
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
- #== FLASHES
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
- flash_notices += add_flash_notices.to_a
114
- flash_alerts += add_flash_alerts.to_a
115
- _flash_id = Rails.configuration.x.render_turbo_stream.flash_id
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
- #== render
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 && turbo_redirect_on_success_to.present?
81
+ if save_action && if_success_turbo_redirect_to.present?
145
82
  response.status = 302
146
- flash[:alert] = flash_alerts
147
- flash[:notice] = flash_notices
148
- Rails.logger.debug(" • Set flash[:alert] => #{flash_alerts}") if flash_alerts.present?
149
- Rails.logger.debug(" • Set flash[:notice] => #{flash_notices}") if flash_notices.present?
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
- turbo_redirect_on_success_to
90
+ if_success_turbo_redirect_to
154
91
  ]
155
92
  ])
156
- elsif save_action && redirect_on_success_to.present?
93
+ elsif save_action && if_success_redirect_to.present?
157
94
  response.status = 302
158
- if (Rails.configuration.x.render_turbo_stream.allow_channel_for_turbo_stream_save rescue false) && (helpers.current_user.id.present? rescue false)
159
- streams.each do |s|
160
- next unless s.is_a?(Hash)
161
- Rails.logger.debug(" • Send by Cable => «#{s}»")
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 redirect_on_success_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
- id: id,
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