0

I have a model called Question, and it has action create;
My goal is to display a flash message instantly, using a helper method (show_alert for example) when the instance is not valid.

question_controller.rb

def create
    question = Question.new(question_params)
    if question.save then
        redirect_to show_question_path(question.id)
    else
        show_alert(:warning, question.errors)
    end
end

application_controller.rb

    helper_method :show_alert

    def show_alert(type, message)
          @type = type; @msg = message
          respond_to do |format|
            format.js { render :template => 'alert.js.erb'}
          end
    end

alert.js.erb

  var div = $('<div></div>').addClass(`alert alert-${@type}`)
  $('<ul></ul>').append( $('<li></li>').html(@msg)
  div.append(ul)
  $('#alerts').html(div)

But instead of displaying the flash, I get only the partial's code on the white screen.

see the screenshot

Since I've used respond_to I got another error: ActionController::UnknownFormat

I need the snippet of code in alert.js.erb to be executed, in order to render the flash, I think the trick is somewhere in the render function, but two hours of googling were just a waste of time.

Please help! Thank you in advance

  • I am not much of an expert myself. Can you please explain whether the create action is invoked by HTML request or JS? Also do you know how respond_to blocks work? – Hussain Niazi Aug 23 '18 at 15:47
  • I would suggest to keep it simple. You should have the javascript function that displays the alert in your html.erb file. And the javascript function in html.erb should execute if there is any error message present. – Hussain Niazi Aug 23 '18 at 15:54
  • Can you share your alert.js.erb as well? – strivedi183 Aug 23 '18 at 18:27
  • @HussainNiazi, yes, the console says `Processing by QuestionController#create as HTML`, I'll try to use `respond_to` – Dan Moskalchuck Aug 24 '18 at 07:07

3 Answers3

0

By default, all output from helpers is escaped. To show the HTMl as-is, you need to use the html_safe method (https://apidock.com/rails/v4.2.1/String/html_safe). See Using helpers in a view escapes the html?

Billy Kimble
  • 798
  • 3
  • 9
0

I cannot be sure this without seeing your alert.js.erb but it could be that you need to use escape_javascript in your alert.js.erb

Something like (and I haven't tested this out) in your alert.js.erb

$('<%= escape_javascript("#{type} - #{msg}") %>').appendTo("#alert")

You can read more about it on Rails Guides - Working With Javascript in Rails

Hope this helps!

strivedi183
  • 4,749
  • 2
  • 31
  • 38
0

ActionController::UnknownFormat error is showing up because the browser is sending HTML request to Rails server, but the respond_to block has only specified what to do in case of a javascript request from web server.

You will need to add a little bit of Ajax to achieve what you want. See this tutorial on Ajax. https://www.tutorialspoint.com/ruby-on-rails/rails-and-ajax.htm

Ajax will send a js request to browser in the background (i.e the browser will not refresh or show any signs of loading). This js request will be sent to Rails server and it will return the .js.erb file containing the script back to the browser. Now since this script was returned as a response to Ajax request by browser, the browser will already know that it is javascript that needs to be executed.

If you do not wish to implement Ajax, you have the alternate of doing something like this in your create controller:-

def create
    question = Question.new(question_params)
    if question.save then
        redirect_to show_question_path(question.id)
    else
        redirect_to new_question_path(error: question.errors) #new_question_path is the action that displays the question form to the user
    end
end

and then you can initialize an error variable in the action that displays the question form. e.g.

def new
    @error=params[:error]
    #rest of the code... 
end

And then in somewhere in your new.html.erb (or whatever the html.erb file name is)

<script>
    <% if @error %>
        var div = $('<div></div>').addClass(`alert alert-<%= @type %>`)
        $('<ul></ul>').append( $('<li></li>').html(<%= @msg %>)
        div.append(ul)
        $('#alerts').html(div)
    <% end %>
    // you might need to tweak the variable names in controller or the above code
</script>

(This code above may not be perfect. its just to give u an idea)

However this approach will not be as quick and beautiful as ajax because when the user will submit their question, the entire page will load again to display the error warning.

Hussain Niazi
  • 579
  • 1
  • 3
  • 21