Могу ли я использовать условия JS в моем файле js.erb Rails 3 для рендеринга партиалов? - PullRequest
1 голос
/ 07 июля 2011

Извините, если это немного сложно. Я постараюсь описать это как можно лучше, но, пожалуйста, задавайте вопросы, если мне неясно.

Я работаю над приложением Rails, которое должно иметь автоматически обновляемую страницу состояния. Эта страница состояния будет иметь запросы, которые имеют много попыток, которые имеют много шагов. Чтобы поддерживать эту страницу настолько актуальной, насколько это возможно, мы используем JQuery для опроса сервера каждые 5 секунд.

Это приводит нас к файлу index.js.erb с помощью действия index. Этот файл в настоящее время настроен для определения (в зависимости от того, что на экране), какие части должны быть перерисованы. Я использую то, что в данный момент на экране, чтобы определить, активен ли еще запрос / попытка / шаг, чтобы узнать, что нужно обновить. Я выбрал это, вместо того, чтобы использовать то, что находится в базе данных, поскольку база данных будет обновлять элемент как неактивный, в результате чего экранный активный элемент не будет обновляться, чтобы показать его новое неактивное состояние .... но, возможно, есть лучший способ обойти это.

Теперь к моей основной проблеме. В моем файле 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 голосов
/ 07 июля 2011

Рассмотрите возможность введения понятия "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 %>";

Сделайте это также для моделей Request и Attempts.

В своем коде обновления добавьте строку запроса last_updated_at к URL-адресу обновления, так что это будет что-то вроде 'http://stats.example.com/index.js?last_updated_at=' + window.last_updated_at.

В стороне: остерегайтесь называть вашу модель Request;в рельсах уже есть класс Request, и вы можете столкнуться с конфликтами.

...