Поток сообщений с использованием JQuery PeriodicUpdater и Rails - PullRequest
2 голосов
/ 17 февраля 2011

Я пытаюсь создать поток сообщений AJAX в моем приложении на Rails 3, используя jQuery. Приложение показывает сообщения и ответы на пост. Сейчас пользователю требуется обновить браузер для обновления:

//in app/views/posts/_replies.html.erb
<div class="replies">
  <% for reply in @replies %>
      <div class="reply">
          <p><%= reply.body %></p>
      </div>
  <% end %>
</div>

Я пытаюсь использовать порт jQuery PeriodicalUpdater (https://github.com/RobertFischer/JQuery-PeriodicalUpdater/), чтобы адаптировать ответы как постоянно обновляемый поток.

Основано на Railscast Райана Бейтса (http://railscasts.com/episodes/136-jquery), вот что у меня есть:

// in public/javascripts/application.js
$(document).ready(function(){
$.PeriodicalUpdater('/replies', {
    method: 'post',
    data: ???,
    minTimeout: 1000,
    maxTimeout: 8000,
    multiplier: 2,
    type: 'json',
    maxCalls: 0,
    autoStop: 0
}, function(data) {
          ????
});
});

Я новичок в js и jQuery, поэтому мне не совсем понятно, как передать текущее сообщение на сервер и как сделать так, чтобы оно автоматически отображало replies. Вот остаток моего кода:

// in app/views/posts/show.js.erb
$("#replies").append("<%= escape_javascript(render 'replies') %>");

// app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def replies
     @replies = Post.find(params[:id]).replies
     respond_to do |format|
       format.js
     end
  end
end

Есть ли способ передать идентификатор текущего post в контроллер? Может быть, даже передать идентификатор последнего reply, чтобы сервер отправлял только новые ответы?

Кроме того, мне нужно вручную добавлять все внутри функции обратного вызова PeriodicalUpdater? Или есть способ сделать частичную show для обновлений?

Обновление : мне понравился @Spencer, предложенный ниже, заменив его на первую кнопку, которую вы нажимаете для обновления AJAX.

У меня проблемы с передачей этого параметра. Мой реальный код ищет вещи на основе уникального URL-ключа, поэтому у меня просто есть:

<input type="button" value="Refresh" onclick="getReplies('<%= @post.url_key %>');" />

Тогда в моем файле application.js:

function getReplies(url_key) {
$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    url: "/replies",
    data: { url_key: url_key },
    success: function(msg) {
        $.each(msg.Replies, function(index, reply) {
            $("#replies").prepend('<p>' + reply.body + '</p>')
        });
    }
});
}

В моем контроллере у меня есть:

def replies
  @post = Post.find_by_url_key(params[:url_key])

  respond_to do |format|
    format.json { render :json => @post.replies }
  end
end

Я получаю:

Processing by PostsController#replies as JSON
Parameters: {"_json"=>"url_key=some-post"}
←[1m←[35mPost Load (1.0ms)←[0m  SELECT `posts`.* FROM `posts` WHERE (`posts`.`url_key` IS NULL) LIMIT 1

Похоже, что параметр не извлекается из params.

1 Ответ

1 голос
/ 17 февраля 2011

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

Второе, что я бы порекомендовал, - это изучить различные шаблонные методы, которые люди используют с jQuery. То есть Ruby должен просто возвращать структуру данных JSON, которую затем можно взять jQuery и заполнить шаблон сообщения различными частями данных.

Вот пример шаблонного метода, который я использовал на одном из моих сайтов. Я начинаю со следующего статического HTML.

    <table id="tblExpenses"><tbody>
        <tr>
            <th>Date</th>
            <th>Title</th>
            <th>Amount</th>
            <th>Attachments</th>
            <th colspan="2">&nbsp;</th>
        </tr>
        <tr class="expenseTemplate" style="display: none;">
            <td class="litDate"></td>
            <td class="litTitle"></td>
            <td class="litAmount"></td>
            <td class="litAttachments">test</td>
            <td><a class="lnkEdit" href="#">Edit</a></td>
            <td><a class="lnkDelete" href="#">Delete</a></td>
        </tr>
    </tbody></table>

Затем я выполняю AJAX-запрос о расходах, хранящихся в базе данных, и динамически создаю новые строки для вставки в таблицу «Расходы».

function showTaxYear(taxYearId) {
    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        url: "/Services/GetExpensesByTaxYearId",
        data: { taxYearId: taxYearId },
        success: function(msg) {
            $.each(msg.Expenses, function(index, expense) {
                var row = $("#tblExpenses tr.expenseTemplate")
                    .clone()
                    .removeClass("expenseTemplate")
                    .show()
                    .addClass("expense")
                    .addClass("expenseid_" + expense.ID);
                row.find("td.litDate").text(expense.Date);
                row.find("td.litTitle").text(expense.Title);
                row.find("td.litAmount").text(expense.Total);
                row.find("a.lnkEdit").attr("data-id", expense.ID)
                                    .unbind().click(function() { editExpense($(this)); });
                row.find("a.lnkDelete").attr("data-id", expense.ID)
                                    .unbind().click(function() { deleteExpense($(this)); });
                if (expense.Attachment != "")
                    row.find("td.litAttachments").empty().append($("<a>View</a>").attr("href", expense.Attachment));
                else
                    row.find("td.litAttachments").empty();
                row.insertBefore("#tblExpenses tr.expenseTemplate");
            });
        }
    });
}

GetExpensesByTaxYearId возвращает результат JSON, который выглядит следующим образом

{"Expenses":[{"ID":9,"Title":"Some expense","Description":"","Date":"02/02/2010","Amount":"$10.00","Tax":0.00,"Attachment":"","Total":"$10.00"}]}

Как только вы это сделаете, вы сможете проверить, действительно ли вы создали элемент для любых данных, которые вы возвращаете из Ruby, выполнив поиск jQuery. Например, в моем примере я могу проверить, существует ли элемент с классом expenseid_<Identifier>. если это произойдет, я уже сделал этот счет.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...