[英]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中。
通过使用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连接到特定的控制器和操作,而无需使用内联脚本标签。
打开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.