Automagically inject flash messages into Ruby on Rails TurboStream responses using Hotwire.
Because it's weird? I don't know.
I originally developed TurboFlash as a proof of concept, but people ended up using it, and, even scarier, contributing back to it. This terrified me because...
I truthfully hate the implementation. It felt like one big hack. I knew a better way to do it. So, here it is, in all its glory, "better", but I still don't like it.
Granted, this implementation is arguably just as "bad" because it intercepts render
, but it's clean, should be relatively safe, and works.
HotFlash is about 100 lines of code, mostly of convenience methods and developer happiness code. It's not scary. This code effectively does the following, so you don't have to:
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post
else
render turbo_stream: [
turbo_stream.replace(:form, "form", locals: { post: @post }),
turbo_stream.replace(:flashes, "shared/flashes") # <-- this
]
end
end
bundle add hot_flash
rails g hot_flash:install
Will copy over an initializer.
It's not enabled out-of-the-box, so you'll need to enable it:
class ApplicationController < ActionController::Base
before_action :enable_hotflash
end
HotFlashes expects you to have a target of #flashes
available, and a method called #render_flash
available as a helper.
module ApplicationHelper
def render_flash
return if @_flash_rendered
render partial: "shared/flash"
end
end
Where app/views/shared/flash.html.erb
renders the flash contents and includes the target selector:
<div id="flashes">
<% flash.each do |key, value| %>
<div><%= key %>: <%= value %></div>
<% end %>
</div>
All flashes are rendered just like they would be in the default request/response cycle; no need to do any of the hack-y junk that TurboFlash did.
class PostsController < ApplicationController
disable_hotflash
end
or,
class PostsController < ApplicationController
disable_hotflash only: [:new]
end
or,
class PostsController < ApplicationController
enable_hotflash only: [:new]
end
HotFlashes has a hotflash
method that you can interact with if you want:
class PostsController < ApplicationController
before_action :disable_hotflash
before_action :interact_with_hotflash
private
def interact_with_hotflash
hotflash.enable!
hotflash.turbo_action = "update"
hotflash.flash_message = :some_other_way_to_show_the_message
hotflash.turbo_target = '#some_other_target'
end
end
flash_method
could probably use some options.
The gem is available as open source under the terms of the MIT License.