2011-07-07 13 views
1

对不起,如果这有点复杂。我会尽力描述它,但如果我不清楚,请提问。我可以在我的Rails 3 js.erb文件中使用JS条件来渲染部分?

我正在开发一个需要自动更新状态页的Rails应用程序。此状态页面将包含请求,其中有许多尝试,其中有很多步骤。为了保持这个页面尽可能最新,我们使用JQuery来每5秒轮询一次服务器。

然后通过index操作将我们带到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

考虑引入的“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查询字符串附加到更新url,所以它类似于'http://stats.example.com/index.js?last_updated_at=' + window.last_updated_at

另外:当心你的模型命名请求;在rails中已经有一个Request类,并且可能会遇到冲突。