ruby-on-railsrubyviewflash-message

Flash is not displayed in the same view in Rails


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.


Solution

  • 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