新手问题 改写 Rails destroy 请求时遇到的问题

liudongyue1987 · 2016年03月14日 · 最后由 dothide 回复于 2016年03月15日 · 2956 次阅读

rails 默认的删除操作代码,像这样

<a href="<%= backend_film_title_path title%>" data-confirm="确定删除吗?" data-method="delete" role="button" ><i class="fa fa-trash-o"></i></a>

这会弹出一个 alert,然后 post 请求到 destroy 这个 action 上. 我觉得这个 alert 很丑,于是想改写这种方式. 我的想法是,点了按钮后先弹出自定义的确认窗口 (不是系统默认的 confirm),然后$.ajax 一个 post 请求到后台的 destory action 上。于是代码像下面这样:

index.html.erb

<table class="table">
  <thead>
    <tr>
      <th>中文名</th>
      <th>英文名</th>
      <th style="width: 3.5em;"></th>
    </tr>
  </thead>
  <tbody>
  <% @film_titles.each do |title| %>
    <tr id="title_<%= title.id %>">
      <td><%= title.chinese_name %></td>
      <td><%= title.english_name%></td>
      <td>
          <a data-toggle='modal' data-target='#modalConfirm' onclick="DeleteConfirm('<%= backend_film_title_path title%>','<%= title.id%>')">删除</a>
          <a href="<%= edit_backend_film_title_path title %>"><i class="fa fa-pencil"></i></a>
      </td>
    </tr>
   <% end %>
  </tbody>
</table>

<!--确认操作对话框-->
<div class="modal small fade" id="modalConfirm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h3 id="myModalLabel">操作确认</h3>
        </div>
        <div class="modal-body">
            <p class="error-text"><i class="fa fa-warning modal-icon"></i>你确定进行该操作?<br>该操作无法撤销.</p>
        </div>
        <div class="modal-footer">
            <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">取消</button>
           <a href="javascript:void(0)" class="btn btn-danger" onclick="DeleteSubmit()">确认</a>
        </div>
      </div>
    </div>
</div>

film_titles.js.erb

window.deleteUrl = '';
window.targetID = '';

function DeleteConfirm(data,id){
  window.deleteUrl = data;
  window.targetID = 'title_'+ id;
}

function DeleteSubmit(argument) {
  $.ajax({
    url: window.deleteUrl,
    type: 'POST',
    dataType: 'json',
    data: {_method: 'delete'},
    success: function(result){
      console.log(window.targetID)
      console.log(result)
      $("#"+window.targetID).closest('tr').fadeOut();
    }
  });
}

上面前端代码的逻辑是: 点击删除按钮,调用 DeleteConfirm 这个 js 方法,给 这两个 window 对象的属性赋值 window.deleteUrl = ''; //这个值像这样:http://localhost:3000/backend/film_titles/23 window.targetID = ''; //这个值像这样:title_23 , 目的是为了 在删除成功后,移除对应的 tr 然后点击弹出的 confirm 对话框的确认按钮,调用 DeleteSubmit 方法,发送一个 ajax 到后台。

film_titles_controller.rb

def destroy
    notice = '删除成功!'
    if !@film_title.destroy
        notice = '删除失败!'
    end
    redirect_to backend_film_titles_path, notice: notice
end

我本意是希望 destroy 方法能返回一个 json 格式的数据,我可以直接通过 js 接收后判定对象的数据,然后处理对应的逻辑,比如下面这样,destroy 这个 action 只返回一个 json 数据,

def destroy
  # notice = '删除成功!'
  # if !@film_title.destroy
  #   notice = '删除失败!'
  # end
  # redirect_to backend_film_titles_path, notice: notice

  render JSON.parse('{ "abc" : 1}')
end

但是,现实不是我想的这样... 我打印出返回结果一直都是;

Template is missing

Missing template backend/film_titles/destroy, backend/application/destroy with {:locale=>[:"zh-CN"], :formats=>[:json, :js, :html, :text, :js, :css, :ics, :csv, :vcf, :png, :jpeg, :gif, :bmp, :tiff, :mpeg, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in:
  * "/Users/liudongyue/LDY/Objects/ruby/film-ocean/app/views"
  * "/Users/liudongyue/.rvm/gems/ruby-2.2.0/gems/kaminari-0.16.3/app/views"

<div id="console"
  data-remote-path='console/repl_sessions/f3102d634ed79be2fdb945a29a2d08a2'
  data-initial-prompt='>> '>
</div>


<script type="text/javascript">
(function() {
  /**
 * Constructor for command storage.
 * It uses localStorage if available. Otherwise fallback to normal JS array.
 */
function CommandStorage() {
......省略....

看这个样子,应该是在我的 film_titles 文件夹下寻找 destroy.html.erb 这个文件. 请问,我该这样修改,才能实现我想要的效果? 问题有点长...感谢回复!

记得华顺有个帖子讲过这个问题,原帖在这里,https://ruby-china.org/topics/29046 我记得一是要有 remote: true ,另一个是 action 要定义 format.js

由于前面是 remote 请求,HTTP Header 里面带的信息会让 Rails 渲染 js.erb 的模板

但具体我也不是很懂,希望能有所帮助吧~ :)

ajax 的 type 应该为 'DELETE'

def destroy
  render json: { abc : 1 }
end

另外,你这里问题比较多。感觉刚接触 Rails 的人,最好身边有 Rails 熟手一起共同进步,不然会走不少弯路的。

#1 楼 @dothide 今天华顺大神写了这个帖子,受益了 https://ruby-china.org/topics/29350

#2 楼 @btc022003 嗯.rails 的约定没记牢...惭愧

#4 楼 @liudongyue1987 恩 看到了 感觉是专门为你写的

#3 楼 @qinfanpeng 按照 2 楼修改了 type,然后再修改 render 出的 json...竟然成功了...原因是我不晓得如何返回正确的 json 数据。非常感谢各位指点。

#6 楼 @dothide 哈哈。要是按照我这种方式做.实在是太曲折了。

#8 楼 @liudongyue1987 呵呵 不过你倒是挺会折腾 换我兴许还想不出这么曲折的路子

需要 登录 后方可回复, 如果你还没有账号请 注册新账号