【问题标题】:Sinatra view doesn't refresh after some delete requests一些删除请求后 Sinatra 视图不刷新
【发布时间】:2018-06-21 06:02:59
【问题描述】:

在我的 Sinatra 视图中,我有一个表格,它将显示我数据库中的所有记录。当我单击删除记录时,我将调用 jquery ajax 来发送删除请求。然后我的路由将处理请求,删除数据库中的记录并将应用程序重定向到其主页。

问题是视图在删除后没有刷新并且仍然显示一些旧数据。当我关闭浏览器并再次打开时,即使删除请求返回了 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

【问题讨论】:

  • sinatra 在您进行 ajax 调用时不会重新加载视图。如有必要,您将不得不使用 javascript 重写 dom。您可以通过 json 返回数据,然后使用该数据刷新表格。

标签: jquery ruby ajax sinatra rack


【解决方案1】:

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

# 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 是否支持这个功能,但现在这个方法就像一个魅力:)

【讨论】:

    【解决方案2】:

    重新加载页面,重定向到页面。

    当您使用 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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-03
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      相关资源
      最近更新 更多