Module: TurboCrud::Helpers
- Defined in:
- lib/turbo_crud/helpers.rb
Instance Method Summary collapse
-
#turbo_crud_container(title:, container: nil, model: nil, close_to_top: true, &block) ⇒ Object
Wrap any existing view inside a TurboCrud container (modal or drawer).
-
#turbo_crud_default_frame_id(model_or_record = nil) ⇒ Object
Decide the default container frame for forms based on configuration.
-
#turbo_crud_drawer_frame ⇒ Object
Drawer frame: like a modal, but it slides in from the side.
-
#turbo_crud_drawer_link(text, url, **options) ⇒ Object
Drawer link: opens URL inside drawer frame.
-
#turbo_crud_flash_frame ⇒ Object
Flash frame: Turbo Streams can replace this for instant feedback.
- #turbo_crud_flash_icon(level) ⇒ Object
- #turbo_crud_flash_level_class(level) ⇒ Object
-
#turbo_crud_flash_messages(notice: nil, alert: nil, source_flash: nil) ⇒ Object
Build normalized flash messages for rendering.
- #turbo_crud_flash_position_class ⇒ Object
-
#turbo_crud_form_with(*args, frame: nil, **kwargs, &block) ⇒ Object
Wrapper around form_with that targets the correct turbo frame.
- #turbo_crud_message_for_level(messages, *levels) ⇒ Object
-
#turbo_crud_modal_frame ⇒ Object
Modal frame: new/edit pages can render inside here.
-
#turbo_crud_modal_link(text, url, **options) ⇒ Object
Modal link: opens URL inside modal frame.
-
#turbo_crud_render_flash(notice: nil, alert: nil, messages: nil) ⇒ Object
Render flash payload using configured renderer.
- #turbo_crud_wrap_app_flash(rendered) ⇒ Object
-
#turbo_list_id(klass_or_relation) ⇒ Object
Example: turbo_list_id(Post) => "posts_list".
-
#turbo_row_id(record) ⇒ Object
Example: turbo_row_id(@post) => "post_123".
Instance Method Details
#turbo_crud_container(title:, container: nil, model: nil, close_to_top: true, &block) ⇒ Object
Wrap any existing view inside a TurboCrud container (modal or drawer).
Usage (in your existing new/edit):
<%= turbo_crud_container title: "New Post" do %>
<%= render "form" %>
<% end %>
The container defaults to TurboCrud.config.default_container (:modal or :drawer), but you can force one:
turbo_crud_container(title: "...", container: :drawer) { ... }
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/turbo_crud/helpers.rb', line 202 def turbo_crud_container(title:, container: nil, model: nil, close_to_top: true, &block) # Capture the block output (the form / content you already have). body = capture(&block) chosen = if container container.to_sym else # Auto-select container from the incoming Turbo frame request. case turbo_crud_requested_frame_id when TurboCrud.config.drawer_frame_id then :drawer when TurboCrud.config.modal_frame_id then :modal else turbo_crud_default_container_for(model) end end # We render a partial shipped by the gem, because HTML is nicer to read there. partial = case chosen when :drawer then "turbo_crud/shared/container_drawer" else "turbo_crud/shared/container_modal" end frame_id = chosen == :drawer ? TurboCrud.config.drawer_frame_id : TurboCrud.config.modal_frame_id turbo_frame_tag(frame_id) do render partial, title: title, body: body, close_to_top: close_to_top end end |
#turbo_crud_default_frame_id(model_or_record = nil) ⇒ Object
Decide the default container frame for forms based on configuration.
If you set default_container = :drawer, forms will target the drawer.
170 171 172 173 174 175 176 177 178 |
# File 'lib/turbo_crud/helpers.rb', line 170 def turbo_crud_default_frame_id(model_or_record = nil) # Prefer the frame requested by the current Turbo visit so drawer/modal # links and form targets stay aligned in existing apps. requested = turbo_crud_requested_frame_id return requested if [TurboCrud.config.modal_frame_id, TurboCrud.config.drawer_frame_id].include?(requested) container = turbo_crud_default_container_for(model_or_record) container == :drawer ? TurboCrud.config.drawer_frame_id : TurboCrud.config.modal_frame_id end |
#turbo_crud_drawer_frame ⇒ Object
Drawer frame: like a modal, but it slides in from the side. 🧊➡️
145 146 147 148 149 150 |
# File 'lib/turbo_crud/helpers.rb', line 145 def turbo_crud_drawer_frame safe_join([ turbo_frame_tag(TurboCrud.config.drawer_frame_id), turbo_crud_behavior_script_once ]) end |
#turbo_crud_drawer_link(text, url, **options) ⇒ Object
Drawer link: opens URL inside drawer frame.
161 162 163 164 165 166 |
# File 'lib/turbo_crud/helpers.rb', line 161 def turbo_crud_drawer_link(text, url, **) [:data] ||= {} [:data][:turbo_frame] = TurboCrud.config.drawer_frame_id [:class] ||= "turbo-crud__drawer-link" link_to(text, url, **) end |
#turbo_crud_flash_frame ⇒ Object
Flash frame: Turbo Streams can replace this for instant feedback.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/turbo_crud/helpers.rb', line 17 def turbo_crud_flash_frame frame_classes = ["turbo-crud__flash-frame", turbo_crud_flash_position_class] safe_join([ turbo_frame_tag( TurboCrud.config.flash_frame_id, class: frame_classes.join(" "), data: { controller: "turbo-crud-flash", turbo_crud_flash_auto_hide_ms_value: TurboCrud.config.flash_auto_hide_ms }.compact ) do turbo_crud_render_flash end, turbo_crud_behavior_script_once ]) end |
#turbo_crud_flash_icon(level) ⇒ Object
116 117 118 119 120 121 122 123 |
# File 'lib/turbo_crud/helpers.rb', line 116 def turbo_crud_flash_icon(level) case level.to_sym when :notice, :success then "✓" when :alert, :error then "!" when :warning then "!" else "i" end end |
#turbo_crud_flash_level_class(level) ⇒ Object
107 108 109 110 111 112 113 114 |
# File 'lib/turbo_crud/helpers.rb', line 107 def turbo_crud_flash_level_class(level) case level.to_sym when :notice, :success then "turbo-crud__flash--notice" when :alert, :error then "turbo-crud__flash--alert" when :warning then "turbo-crud__flash--warning" else "turbo-crud__flash--notice" end end |
#turbo_crud_flash_messages(notice: nil, alert: nil, source_flash: nil) ⇒ Object
Build normalized flash messages for rendering.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/turbo_crud/helpers.rb', line 35 def (notice: nil, alert: nil, source_flash: nil) = [] << { level: :notice, text: notice.to_s } if notice.present? << { level: :alert, text: alert.to_s } if alert.present? # If explicit locals were passed, don't merge session flash to avoid stale leakage. return if notice || alert flash_source = source_flash || flash level_map = TurboCrud.config.flash_levels || {} level_map.each do |source_key, level| value = flash_source[source_key] next if value.blank? << { level: level.to_sym, text: value.to_s } end .uniq end |
#turbo_crud_flash_position_class ⇒ Object
125 126 127 128 129 130 131 132 133 134 |
# File 'lib/turbo_crud/helpers.rb', line 125 def turbo_crud_flash_position_class case TurboCrud.config.flash_position.to_sym when :top_center "turbo-crud__flash-frame--top-center" when :inline "turbo-crud__flash-frame--inline" else "turbo-crud__flash-frame--top-right" end end |
#turbo_crud_form_with(*args, frame: nil, **kwargs, &block) ⇒ Object
Wrapper around form_with that targets the correct turbo frame.
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/turbo_crud/helpers.rb', line 181 def turbo_crud_form_with(*args, frame: nil, **kwargs, &block) model_for_defaults = turbo_crud_model_from_form_args(args, kwargs) resolved_frame = frame || turbo_crud_default_frame_id(model_for_defaults) kwargs[:data] ||= {} kwargs[:data][:turbo_frame] ||= resolved_frame # Auto-disable submit controls while request is in flight (opt out by passing # data: { turbo_crud_auto_disable: false } on a specific form). kwargs[:data][:turbo_crud_auto_disable] = true unless kwargs[:data].key?(:turbo_crud_auto_disable) form_with(*args, **kwargs, &block) end |
#turbo_crud_message_for_level(messages, *levels) ⇒ Object
95 96 97 98 |
# File 'lib/turbo_crud/helpers.rb', line 95 def (, *levels) match = .find { || levels.include?([:level].to_sym) } match && match[:text] end |
#turbo_crud_modal_frame ⇒ Object
Modal frame: new/edit pages can render inside here.
137 138 139 140 141 142 |
# File 'lib/turbo_crud/helpers.rb', line 137 def turbo_crud_modal_frame safe_join([ turbo_frame_tag(TurboCrud.config.modal_frame_id), turbo_crud_behavior_script_once ]) end |
#turbo_crud_modal_link(text, url, **options) ⇒ Object
Modal link: opens URL inside modal frame.
153 154 155 156 157 158 |
# File 'lib/turbo_crud/helpers.rb', line 153 def turbo_crud_modal_link(text, url, **) [:data] ||= {} [:data][:turbo_frame] = TurboCrud.config.modal_frame_id [:class] ||= "turbo-crud__modal-link" link_to(text, url, **) end |
#turbo_crud_render_flash(notice: nil, alert: nil, messages: nil) ⇒ Object
Render flash payload using configured renderer.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/turbo_crud/helpers.rb', line 58 def turbo_crud_render_flash(notice: nil, alert: nil, messages: nil) normalized = || (notice: notice, alert: alert) renderer = TurboCrud.config.flash_renderer if renderer.respond_to?(:call) return renderer.call(self, messages: normalized) end return "".html_safe if normalized.blank? locals = { messages: normalized, notice: (normalized, :notice, :success), alert: (normalized, :alert, :error, :warning) } partial = case renderer when :off, :none return "".html_safe when :app, :rails_default "shared/flash" when nil, :default then "turbo_crud/shared/flash" else renderer.to_s end rendered = render partial: partial, locals: locals return turbo_crud_wrap_app_flash(rendered) if i[app rails_default].include?(renderer) rendered rescue ActionView::MissingTemplate return "".html_safe if i[off none app rails_default].include?(renderer) # For explicit custom paths, fall back to safe default. render partial: "turbo_crud/shared/flash", locals: locals end |
#turbo_crud_wrap_app_flash(rendered) ⇒ Object
100 101 102 103 104 105 |
# File 'lib/turbo_crud/helpers.rb', line 100 def turbo_crud_wrap_app_flash(rendered) html = rendered.to_s return rendered if html.include?("turbo-crud__flash-stack") tag.div(rendered, class: "turbo-crud__flash-stack", aria: { live: "polite", atomic: "true" }) end |
#turbo_list_id(klass_or_relation) ⇒ Object
Example: turbo_list_id(Post) => "posts_list"
6 7 8 9 |
# File 'lib/turbo_crud/helpers.rb', line 6 def turbo_list_id(klass_or_relation) klass = klass_or_relation.respond_to?(:klass) ? klass_or_relation.klass : klass_or_relation "#{klass.model_name.plural}_list" end |
#turbo_row_id(record) ⇒ Object
Example: turbo_row_id(@post) => "post_123"
12 13 14 |
# File 'lib/turbo_crud/helpers.rb', line 12 def turbo_row_id(record) dom_id(record) end |