簡體   English   中英

Rails + JS + Ajax請求

[英]Rails + JS + Ajax request

嗨,我正在用Rails + JS + Ajax對Waldo(Wally)進行簡單的游戲克隆。 這個想法是:玩家變成3張圖像,並且必須檢查3個字符(Waldo,Wilma,Wizard)在哪里。 3.之后,圖像顯示字段以提交名稱,提交后顯示高分列表。

到目前為止,我已經編寫了時間機制(帶有setInterval的JS變量),點數(JS + AJAX + rails控制器)的機制,但我無法為提交名稱,點數和模型時間編寫動作代碼。

我的查看文件:

<%= form_tag('/check/highscore',  method: :post, format: :js, remote: true ) do %> 
    <%= text_field_tag 'name', 'enter your name' %>
    <%= submit_tag 'submit' %>
  <% end %>

<script type="text/javascript">
 $.ajax({
 url: "<%= highscore_check_index_path %>",
 type: "POST",
 format: "js",
 dataType: "script",
 data: { username: $(this).username, score: guessd, time: time  }, 
 success: function(data) {
 $('send_highscore').append('data.username')    
 window.waldo.HS()
},
});
};

我的控制器文件:

def highscore
 @username = params[:name] 
 respond_to do |format|
  format.js { render :layout => false } 
  format.html
 end
end
def highscore2
 record = Highscore.new 
 record.username = params[:username]
 record.score = params[:score] 
 record.time = params[:time]
 record.save 
end 

我的highscore.js.erb

console.log("<%=j @username %>");

window.waldo.HS = function(username) {
 $.ajax({
  url: "<%= highscore2_check_index_path %>",
  type: "POST",
  format: "js",
  data: { username: name, score: guessd, time: time  }, 
  success: function(data) {
  console.log(data);
 $('send_highscore').append('data.username')    
}
});
});

我知道,我的頌歌質量很差,但是我現在嘗試學習。 問題是,盡管我在渲染為js腳本文件的螢火蟲中看到了highscore.js.erb,但並未執行。 highscore.js.erb的想法是將ruby和js變量混合在一起,並一起發送到check控制器中執行highscore2操作並保存到db中。

js.erb是一種不好的學習方式。

通過使用remote: true並返回JS.erb響應,Ruby on Rails可以用作窮人的單頁體系結構。 但實際上,它確實給了您足夠的繩索來吊住自己。

這是學習ajax的一種非常糟糕的方法,因為它導致糟糕的代碼組織和非常不RESTful的應用程序,因為它導致對過程而不是資源的關注。

相反,我鼓勵您嘗試在不混合ERB和JS的情況下學習Ajax。 混合服務器端和客戶端邏輯只會使一切變得更加復雜,因為您必須跟蹤發生在哪里的情況。

相反,您可能需要集中精力在app/assets/javascripts設置可重用的javascript函數,並獲取JSON數據而不是javascript過程。

這不僅會教您在Rails中執行Ajax,而且還將教您如何使用外部API進行Ajax,並教給您有關如何構造和組織代碼的寶貴經驗。

因此,讓我們開始看看如何重構:

高分應該是一種資源。

讓我們從設置路線開始:

resources :highscores, only: [:create, :index, :show]

和控制器:

class HighscoresController < ApplicationController
  respond_to :json, :html

  def create
    @highscore = Highscore.create(highscore_params)
    respond_with @highscore
  end

  def index
    @highscores = Highscore.order(score: :desc).all
    respond_with @highscores
  end

  def show
    @highscore = Highscore.find(params[:id])
    respond_with @highscore
  end

  private
    def highscore_params
      params.require(:highscore).permit(:username, :time, :score)
    end
end

響應者是一個非常出色的工具,它使它變得無用,因此在返回響應時,我們不必做大量的樣板代碼。 如果成功,我們的create方法將返回200 OK如果失敗,則返回422 BAD ENTITY或其他“錯誤”響應代碼。

一些javascript腳手架

讓我們設置一些腳手架,以便我們可以將javascript連接到特定的控制器和操作,而無需使用內聯腳本標簽。

打開layouts/application.html.erb並替換<body>標簽:

<%= content_tag :body, data: { action: action_name, controller: controller_name } do %>
  <%= yield %>
<% end %>

然后將這小塊添加到applicaiton.js

// Triggers events based on the current controller and action.
// Example:
// given the controller UsersController and the action index
// users:loaded
// users.index:loaded
$(document).on('page:change', function(){
  var data = $('body').data();
  $(this).trigger(data.controller + ":loaded")
         .trigger(data.controller + "." + data.action + ":loaded");
});

那個阿賈克斯你們都在說話嗎?

可以說,我們有一個高分列表,我們要定期(輪詢)或在用戶提交高分時進行更新。

// app/assets/javascripts/highscores.js
function getHighscores(){
  var $self = $('.highscores-list');
  return $.getJSON('/highscores').done(function(highscores){
    var elements = $.map(highscores, function(h){
      return $('<li>').text([h.username, h.score].join(', '));
    });
    $self.empty().append(elements);
  });
};

$(document).on('games:loaded highscores:loaded', function(){
  // refresh highscores every 5 seconds
  (function refresh(){
    getHighscores().done(function(){
      window.setTimeout(refresh, 5000);
    });
  }());
});

最后一部分有點麻煩-它的遞歸函數在ajax調用完成時設置一個新計時器。 我們使用這個而不是setInterval的原因是setInterval不在乎上一個調用是否完成。

創建高分。

首先讓羅素建立表格:

<%# app/views/highscores/_form.html.erb %>
<%= form_for(local_assigns[:highscore] || Highscore.new), class: 'highscore-form' do |f| %>
  <div class="field">
    <%= f.label :username %>
    <%= f.text_field :username %>
  </div>
  <%= f.hidden_field :score %>
  <%= f.hidden_field :time %>
  <%= f.submit %>
<% end %>

然后讓它具有一些ajax的優點:

$(document).on('games:loaded highscores:loaded', function(){
  $('#new_highscore').submit(function(e){
    $.ajax(this.action, {
      data: {
        highscore: {
          username: this.elements["highscore[username]"].value,
          time: this.elements["highscore[time]"].value,
          score: this.elements["highscore[score]"].value
        }
      },
      method: 'POST',
      dataType: 'JSON'
    }).done(function(data, status, jqXHR){
      getHighscores();
      // todo notify user
    });
    return false; // prevent form from being submitted normally
  });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM