Flash is not displayed in the same view in Rails
Asked Answered
J

1

4

I need to display flash in the same view (:edit) after successfully updating an object. If I redirect to another action - everything works correctly. But when I need to stay in :edit - doesn't work. Can someone explain to me what is my mistake... Thanks!

I have the following snippet of code in my controller:

  def edit
    @setting = Setting.find_by(slug: current_user)
  end

  def update
    @setting = Setting.find_by(slug: current_user)

    if @setting.update(settings_params)
      flash[:success] = I18n.t('admin.settings.edit.success')
    else
      flash[:danger] = I18n.t('admin.settings.edit.not_saved')
    end

    redirect_to edit_admin_setting_url(user: current_user)
  end

routes.rb:

scope ":user/" do
  namespace :admin do
    resource :setting, only: [:edit, :update]
  end
end

And edit.html.erb

      <% if flash[:success].present? %>
        <div class="<%= classes + "alert-success" %>">
          <%= icon("fas", "check") %>

          <%= flash[:success] %>

          <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
      <% end %>

I also tried:

flash.now[:success] = I18n.t('admin.settings.edit.success')
render :edit

Doesn't work either.

Josie answered 4/4, 2022 at 7:50 Comment(0)
B
7

In Rails 7 turbo expects POST / PUT / PATCH form submissions to redirect, usually that's create and update controller actions.

To render a template, the response has to have an invalid status, like :unprocessable_entity, otherwise turbo shows an error in the browser console:

turbo.es2017-esm.js:2115 Error: Form responses must redirect to another location
    at k.requestSucceededWithResponse (turbo.es2017-esm.js:679)
    at A.receive (turbo.es2017-esm.js:450)
    at A.perform (turbo.es2017-esm.js:431)

Rails 7 signup form doesn't show error messages

This is one way to set up an update action:

# GET /:user/admin/setting/edit
#
# renders edit.html.erb
def edit
  @setting = Setting.find_by(slug: current_user)
end

# PATCH /:user/admin/setting
#
# redirects to user on success
# renders edit.html.erb on failure
def update
  @setting = Setting.find_by(slug: current_user)

  if @setting.update(settings_params)
                                # when setting updated

    flash[:success] = "Success" # set a message to show on the next request;
                                # we have to redirect to another url

    redirect_to user_url(current_user)
                                # redirect some place else, like user profile
                                # this means we're done with `update` action 
                                # and with current request

  else                          # when update/validation failed
                                # we cannot redirect, because we'll loose our
                                # invalid object and all validation errors
                                # NOTE: sometimes if redirect is required
                                #       errors can be assigned to `flash`

    flash.now[:danger] = "Oops" # set a message to show in this request; 
                                # we have to render a response
                                # NOTE: this might be unnecessary, because form
                                #       will also show validation errors

    render :edit, status: :unprocessable_entity
                                # render edit.html.erb template,
                                # this means we're staying in `update` action 
                                # and in current request
                                # NOTE: this has nothing to do with `edit`
                                #       action at the top
  end
end

You can also use rails generators to get a quick starting code and an example of how everything works.

bin/rails generate scaffold Sample name email
bin/rails db:migrate
Brimmer answered 4/4, 2022 at 9:58 Comment(1)
You saved me, damn. I don't think turbo expects btw, turbo demands. If you don't include the status, Rails won't display your flash.now message at all and there's no error in the browser console.Eijkman

© 2022 - 2024 — McMap. All rights reserved.