对不起,如果这有点复杂。我将尝试尽可能地描述它,但如果我不清楚,请提出问题。
我正在开发一个需要自动更新状态页面的Rails应用程序。此状态页面将具有请求,其具有许多尝试,其具有许多步骤。为了尽可能保持此页面的最新状态,我们使用JQuery每5秒轮询一次服务器。
然后通过索引操作将我们带到index.js.erb文件。此文件当前设置为(根据屏幕上的内容)确定需要重新呈现的部分。我使用屏幕上当前的内容来确定请求/尝试/步骤是否仍处于活动状态以了解需要刷新的内容。我选择了这个,而不是使用数据库中的内容,因为数据库会将项目更新为非活动状态,导致屏幕上的活动项目不会更新以显示它的新的非活动状态....但也许有更好的方法此
现在我的主要问题。在我的erb文件中,我有很多:
if (some statement) {<%= escape_javascript(render :partial=>"my_partial") %>}
,无论在什么条件下,都会评估脚本中提到的所有部分。这将以指数方式增加渲染时间,并且似乎在我们的服务器上受到重创。
有没有办法根据屏幕上当前的内容有条件地渲染部分内容?
对整个考验有没有更好的方法?我知道动态更新的状态页面到处都是,但找不到一个很好的例子来引导我朝着正确的方向发展。
此外,这里是我的一些实际代码的片段,可能提供我正在做的更好的例子。我对复杂的javascript很新,所以如果我有一些完全不合适的东西,请告诉我。
<%attempt.steps.each do |step| %>
/* If a status for this step already exists on the page, only update portions of it, otherwise append the step status to the page */
if (document.getElementById("step-status-<%= step.id %>")) {
$("#step-status-<%= step.id %>").html('<%= escape_javascript(render :partial=>'step_status', :locals=>{:step=>step}) %>');
<% if step.log.present? #log will be present once step is complete %>
/* If the log isn't displayed on the page, add the partial to display it. This is supposed to allow for this partial to only be rendered once and not refreshed*/
if ($("#step-<%= step.id %>-log pre").is(":empty")) {
$("#step-<%= step.id %>-log").html('<%= escape_javascript(render :partial=>'log_details', :locals=>{:step=>step}) %>');
$("#step-<%= step.id %>-log-button").html('<%= escape_javascript(link_to("View Log", "#", :id=>"step-#{step.id}")) %>');
}
<% end %>
} else {
$("#step-details-list-<%= attempt.id %>").append('<%= escape_javascript(render :partial=>"step", :locals=>{:step=>step}) %>');
}
<% end %>
非常感谢您的帮助。
崔西
答案 0 :(得分:0)
考虑将“last_updated_at”的概念引入您的客户端。
在您的控制器中:
def index
# Lets pretend the earliest you're interested in is 1 day ago
updated_since = params[:last_updated_at].try(:to_time) || 1.day.ago
# For ease, i'm doing the query here; this query may be more appropriate as a scope in the model
@steps = Steps.where(["updated_at > ?", updated_since])
end
在index.js.erb视图中:
<% @steps.each do |step| %>
var step_html = '<%= escape_javascript(render :partial=>'log_details', :locals=>{:step=>step}) %>';
var step_ele = $('#step-<%= step.id %>')[0];
if (step_ele) {
// Step was already in the page; just replace it
step_ele.html(step_html);
}
else {
// Step isn't on the page yet; append it to its container
$('#step-container').append(step_html);
}
<% end %>
window.last_updated_at = "<%= Time.now.to_s %>";
也可以为您的请求和尝试模型执行此操作。
在更新代码中,将last_updated_at查询字符串附加到更新网址,因此类似于'http://stats.example.com/index.js?last_updated_at=' + window.last_updated_at
。
除此之外:谨防命名您的模型请求;在rails中已有一个Request类,您可能会遇到冲突。