我可以在我的Rails 3 js.erb文件中使用JS条件来渲染部分内容吗?

时间:2011-07-07 04:36:11

标签: jquery ruby-on-rails erb partials

对不起,如果这有点复杂。我将尝试尽可能地描述它,但如果我不清楚,请提出问题。

我正在开发一个需要自动更新状态页面的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  %>

非常感谢您的帮助。

崔西

1 个答案:

答案 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类,您可能会遇到冲突。