Reputation: 139
I am trying to have jquery enabled after the redirect_to update_path, I have tried disabling turbolinks all-together, but that doesn't help. I am currently doing a window.location.reload() function on successful update, but it is a horribly ugly work around. Is there a better way to accomplish this?
this is in .js
$.ajax ({
type: 'POST',
url: "http://localhost:3000/chess/" + sv + "/" + val,
success: function(d){
count = 0;
window.location.reload();
}
});
this is in the controller.rb:
def move
piece = params[:piece].chomp(",").each_char.map(&:to_i)
a = piece[0]
b = piece[2]
square = params[:square].chomp(",").each_char.map(&:to_i)
c= square[0]
d= square[2]
pieceVal = @@arr[a][b]
squareVal = @@arr[c][d]
@@arr = @@arr.each_with_index.map do | e1, i1|
@@arr[i1].each_with_index.map do |e2, i2|
if (i1 === a && i2 ===b)
@@arr[a][b] = [0]
elsif (i1 === c && i2 === d)
@@arr[c][d] = pieceVal
else
e2 = @@arr[i1][i2]
end
end
end
redirect_to update_path
end
I tried setting turbolinks: false after redirect, but that just disabled the jquery completely.
Upvotes: 0
Views: 322
Reputation: 5363
Sorry for the book: I thought I'd explain what's going on instead of just giving you an answer.
So turbolinks is a non-issue here. The issue is in your implementation (and it's not that big of issue)
When you write redirect_to ...
, it tells your browser go to to the Location
as specified in the response header. It returns no body (like a GET request returns a body of HTML)
The trick here is to implement some way of replacing the content of the chess board with the new chess board, without reloading the entire page. Because we already know the output of the new chess board, we can do that with javascript.
HTTP requests (think of them as the results of controller methods) can respond to many different formats. You're already familiar with HTML responses, those are standard. There are other formats, including (but not limited to) XHR requests (stands for XML HTTP Request) and JSON requests.
Similarly to my response to a question you asked yesterday, you can see the difference by adding the following into application_controller.rb
(assuming you added the other code as well):
def test
respond_to do |format|
format.html { render :text => "I love me some #{params[:cookies]} with my #{params[:cream]}" }
format.json { render :json => { :result => "I love me some #{params[:cookies]} with my #{params[:cream]}", :cookie_result => params[:cookies], :what_kind_of_cream_did_he_want => params[:cream] }
format.js { render :text => "alert('I love me some #{params[:cookies]} with my #{params[:cream]}');" }
end
end
And then hitting localhost:3000/chocolate-chip/and/milk.json
in your browser to view the resulting JSON, for example.
Of note: Rails expects XHR requests (most of the time, a response for ajax requests) to have a format
of js
, don't let it trip you up.
We can't call localhost:3000/chocolate-chip/and/milk.xhr
because we have no MIME type for it; a browser doesn't know how to handle it, and our Rails server (like puma or webrick) don't know how what to do with it. That's fine, and normal.
XHR requests are a client-side thing (in terms of your HTML/JS). They can be likened to how you send a POST request: you instruct the browser to do something.
What we want to do is tell the browser to send an ajax request. Thankfully, Rails makes this easy if you're using jquery_ujs
(which you probably are, just check your application.js
file for it)
To view our generated XHR response from the example above, put <%= link_to "What kind of cookies", "/chocolate-chip/and/milk", :remote => true %>
somewhere in an existing *.html.erb
file that you can view. Go ahead and click it. It should return an alert box exclaiming our love for chocolate chips and milk.
As you can see, our inline javascript is executed.
So now the question is "how can I get my chess board to be replaced with this?"
The best practice for this is to have a partial
of _board.html.erb
that renders the board. <div id="chess_board_wrapper"><%= render 'board' %></div>
if it's in the same view path that the controller expects (per Rails conventions, and you should be following them). Note: having an ID attribute in the parent element of the rendered chess board is important here; we'll need it later.
Inside _board.html.erb
, just copy-pasta your existing chess board markup.
Now, create a move.js.erb
(yes, .js.erb
), just like you would a new.html.erb
. Inside that move.js.erb
file, you can simply write $('#chess_board_wrapper').html('<%=j render "board" %>');
Then, tell your move
method to respond to XHR requests,
def move
# ...
respond_to do |format|
format.js # should automatically read move.js.erb
format.html { redirect_to update_path }
end
end
and the rest is history. I'm pretty sure that you can remove the success
function from your ajax call as well.
Upvotes: 2