Sinatra 视图在一些删除请求后不刷新

Sinatra view doesn't refresh after some delete requests

在我的 Sinatra 视图中,我有一个 table,它将显示我数据库中的所有记录。当我点击删除一条记录时,我会调用jqueryajax发送删除请求。然后我的路线将处理请求,删除数据库中的记录并将应用程序重定向到其主页。

问题是删除后视图没有刷新,仍然显示一些旧数据。当我关闭浏览器并再次打开它时,即使删除请求已返回 200 代码状态,数据仍然存在于视图中。

# 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

下面是视图的简化代码:

# index.erb

<% if !@links.empty? %>
<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 %>

这是 GitHub 上的完整源代码:https://github.com/huyvohcmc/bitly

好吧,经过几个小时的谷歌搜索,我终于可以通过稍微更改控制器和视图来使其工作:

# 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();
      }
    })
  }

基本上,删除记录后我必须手动重新加载页面。我还不知道 Sinatra 是否支持这个功能,但现在这个方法很有用:)

正在重新加载一个页面并且正在重定向到一个页面。

当您使用 Sinatra 的 redirect 方法时,它会响应 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

通过调用 redirect "/",您要求浏览器重定向到“/”,这通常会触发一个新页面。但是,您已经在该页面上,因此 jQuery 代码正在接收重定向 并且 您要求在成功时通过 location.reload() 重新加载。成功通常通过使用 2xx 代码进行响应来表示,因此我认为重定向意味着成功处理程序未触发,并且因为浏览器意识到您已经在页面上,重定向要求它不会尝试一个重定向,你最终没有新数据。

路线可能看起来更像这样:

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

成功处理程序现在应该触发。这个故事的寓意,明确你想做什么,不要依赖副作用(比如重定向共享重新加载的一些属性)来做你想做的事。