Huy Vo
Huy Vo

Reputation: 2500

Sinatra view doesn't refresh after some delete requests

In my Sinatra view, I have a table which will display all records from my database. When I click to delete a record I will call the jquery ajax to send the delete request. My route will then handle the request, delete the record in the database and redirect the app to its homepage.

The problem is that the view doesn't refresh after delete and still show some old data. When I close the browser and open it again the data still exists in the view even though the delete request has returned 200 code status.

# application_controller.rb

require 'sinatra'
require 'sinatra/reloader'
require './application_helper' if development?

enable :logging

helpers ApplicationHelper

...

delete '/delete/:record_id' do
  id = get_record_id
  delete_record id
  redirect '/'
end

get '/' do
  @links = get_all @user_ip
  erb :index, { :layout => :layout }
end

And here is the simplified code of the view:

# index.erb

<% if [email protected]? %>
<div class="table-responsive" style="margin-top: 30px">
  <table class="table table-striped table-hover" style="width: 600px">
    <thead>
      <tr>
        <th>Original URL</th>
        <th>Short URL</th>
        <th>Delete</th>
      </tr>
    </thead>
    <tbody>
      <% @links.each do |record| %>
        <tr>
          <td><a href=<%= record.long_url %>><%= record.long_url %></td>
          <td><a href=<%= record.id %>><%= record.short_url %></td>
          <td>
            <button class="btn btn-default" onClick="deleteRecord(<%= record.id %>)">
              <span class="glyphicon glyphicon-trash" style="color: red"></span>
            </button>
          </td>
        </tr>
      <% end %>
    </tbody>
  </table>
</div>
<% end %>

Here is the full source code on GitHub: https://github.com/huyvohcmc/bitly

Upvotes: 1

Views: 431

Answers (2)

ian
ian

Reputation: 12251

There is reloading a page and there is redirecting to a page.

When you use the redirect method of Sinatra it responds with a 302 or 303 status code.

# @see https://github.com/sinatra/sinatra/blob/v2.0.0/lib/sinatra/base.rb#L271
# Halt processing and redirect to the URI provided.
def redirect(uri, *args)
  if env['HTTP_VERSION'] == 'HTTP/1.1' and env["REQUEST_METHOD"] != 'GET'
    status 303
  else
    status 302
  end

  # According to RFC 2616 section 14.30, "the field value consists of a
  # single absolute URI"
  response['Location'] = uri(uri.to_s, settings.absolute_redirects?, settings.prefixed_redirects?)
  halt(*args)
end

By calling redirect "/" you are asking the browser to redirect to "/", which would normally trigger a fresh page. However, you're already on that page, so the jQuery code is receiving a redirect and you're asking for a reload via location.reload() upon success. Success is generally indicated by responding with a 2xx code, so I'd posit that the redirect means the success handler isn't firing, and because the browser realises you're already on the page the redirect has asked for it doesn't attempt a redirect either and you end up with no fresh data.

The route should probably look more like this:

delete '/delete/:record_id' do
  id = get_record_id
  delete_record id
  halt 200 # think about handling errors too
end

The success handler should now fire. Moral of the story, be explicit in what you want to do, don't rely on side effects (like a redirect sharing some properties of a reload) to do what you want.

Upvotes: 1

Huy Vo
Huy Vo

Reputation: 2500

Well after some hours googling I can finally make it to work by changing both the controller and the view a little bit:

# application_controller.rb

delete '/delete/:record_id' do
  id = get_record_id
  delete_record id
  redirect '/'
end

# index.erb

var deleteRecord = function (id) {
    $.ajax({
      url: '/delete/' + id,
      type: 'DELETE',
      success: function(data) {
        location.reload();
      }
    })
  }

Basically, I have to reload the page manually after deleting a record. I don't know yet if Sinatra support this functionality but for now this method works like a charm :)

Upvotes: 1

Related Questions