我知道这是一个很受欢迎的话题,但我一直在搜索相当多试图找到答案,奇怪的是没有发现任何能够帮助…
我有一个基本的Rails 3应用程序在表中显示数据库条目。一个单独的应用程序将新条目发布到数据库中,我希望Rails应用程序轮询和刷新以显示新内容。现在,我有一个可怕的javascript片段,只是简单地重新加载整个页面,它被证明是我的障碍。我有一个搜索栏和检查栏来删除多个项目,但这些都是重置在页面刷新(再次,我知道这是可怕的,可怕的破坏)。
从我所阅读的内容来看,我认为应该使用AJAX轮询数据库,并简单地呈现比最新显示的条目更新的数据库条目。如何精确地执行这是另一个故事…
我找到的大多数教程都已经过时了,我一直无法让遗留代码运行。我对AJAX和Rails都是新手,如果有人有任何指导、建议、教程或个人批评(:P),我将非常高兴,这可能会给我指明正确的方向。
谢谢!
编辑:我有新的条目被拉入页面,但他们没有正确渲染。由于某种原因,它们没有作为条目添加到我的表中。这是我的代码,希望你们能挑出我错过的东西:*注->请求实际上是我的数据库条目的名称。请求是模型。
视图/请求/index.html.erb
<table class="center">
<div id="requests">
<tr>
<th><%= sortable "Patient_Name", "Patient Name" %></th>
<th><%= sortable "Room_Number", "Room Number" %></th>
<th><%= sortable "Request" %></th>
<th><%= sortable "Urgency" %></th>
<th><%= sortable "count", "Request Count" %></th>
<th><%= sortable "created_at", "Created At" %></th>
<th></th>
</tr>
<%= render @requests %>
</div>
</table>
请求部分:views/requests/_request.html.erb
<div class="request" data-time="<%= request.created_at.to_i %>">
<tr>
<td><%= request.Patient_Name %></td>
<td><%= request.Room_Number %></td>
<td><%= request.Request %></td>
<td><%= request.Urgency %></td>
<td><%= request.count %></td>
<td><%= request.created_at.getlocal.strftime("%r on %D") %></td>
<td><%= link_to 'Remove', request, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
</div>
视图/请求/index.js.erb
$('#requests').append("<%=raw escape_javascript(render(@requests))%>");
这是怎么回事?
http://www.datatables.net/另一组在这里:
http://plugins.jquery.com/plugin-tags/ajax-table有时候,利用已有的东西比创造新的更好。
但是要回答你的问题,这取决于你是自己操纵DOM还是让Prototype、jQuery、MooTools或其他什么来做繁重的工作。这个想法是在Javascript中设置一个计时器,当计时器触发时,请求服务器更新。服务器——你的Rails应用程序——将打包任何更改并发送回来。
步骤1:决定一个框架。我用jQuery,但大多数人都会用。
步骤2:确定数据格式。我使用JSON,但是XML也可以。
步骤3:设置定时器循环。它涉及到使用settimer()并在每次观察后重置它。
步骤4:在计时器触发时执行的处理程序中,打包一个"最后一次看到"的时间戳并发出Ajax请求。如何做到这一点因框架而异——或者如果您直接编码到DOM,则因浏览器而异。
步骤5:设置一个"success"处理程序,这样当你的服务器返回零行或多行数据时,你可以在你的表中插入这些TR-TD-/TD-/TR行。
步骤6:更新任何内部垃圾,如数字或行计数器或其他任何你的Javascript正在跟踪。
注意:你可能会发现别人写的插件效果很好,帮你省去了麻烦,但是你应该对如何做到这一点有一个基本的了解
首先创建一个可以获取新条目的rails端点:
# config/routes.rb
match '/records/new_since/:time', :to => 'records#new_since'
# app/controllers/records_controller.rb
class RecordsController < ApplicationController
def new_since
@records = Record.where('created_at > ?', Time.parse(params[:time]))
respond_to do |format|
format.json do
@records[:time] = Time.now.to_s(:db)
render :json => @records.to_json
end
end
end
end
然后,在客户端添加一点javascript(这里是原型):
setInterval(
function(){
new Ajax.Request('/records/new_since/' + $('time') + '.json', {
method: 'get',
onSuccess: function(transport){
var records = transport.response.responseJSON;
// insert the last checked time into <div id='time'></div>
$('time').innerHTML = records.time;
// loop over response JSON and do what you want with the data
records.each(function(record){
$$('table#records').insert({
bottom: '<tr><td>'+record.attribute+'</td></tr>';
});
});
}
});
},
30000
);
或者,不发送json,您可以呈现所有新表行的模板,并将其也扔进去。不太灵活,但如果您只想将响应放在底部,则更简单:
def new_since
@records = Record.where('created_at > ?', Time.parse(params[:time]))
respond_to do |format|
format.json {} # renders json template
end
end
# app/views/records/new_since.html.json.erb
<% records.each do |record| %>
<tr><td><%= record.attribute %></td></tr>
<% end %>
setInterval(
function(){
new Ajax.Request('/records/new_since/' + $('time') + '.json', {
method: 'get',
onSuccess: function(transport){
var record_rowss = transport.response.responseText;
$('time').innerHTML = records.time;
$$('table#records').insert({bottom: record_rows});
}
});
},
30000
);