Рендеринг HTML из задания на страницу в Rails 5

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

class CommentsJob < ApplicationJob
  queue_as: default
  def perform(commenter_company)
   @comments = Comment.where(company: commenter_company)
   @html = CommentsController.render partial: "comments", assigns {comments: @comments }
  end
end

У меня уже есть частичная настройка _comments.html.erb. У меня также установлен асинхронный адаптер очереди, поэтому это задание действительно выполняется в фоновом режиме и завершается после загрузки страницы.

Я успешно могу получить html и установить его в переменную экземпляра @html в задании.

Мой вопрос: как я могу получить этот контент @html на странице, которая уже отображается? Можно ли это сделать из работы или мне нужно использовать ActionCable/websockets для этого? Заранее спасибо!


person bcan001    schedule 15.01.2016    source источник
comment
Это похоже на то, для чего вы должны использовать javascript. Я почти уверен, что частично покажу, что вам понадобится либо жесткое обновление, либо какой-то тип JS.   -  person ruby_newbie    schedule 15.01.2016
comment
Вам придется реализовать некоторое кэширование. То, что вы пытаетесь сделать, это разогрев кеша. См. Кэширование куклы России с рельсами   -  person Cristian Bica    schedule 15.01.2016
comment
Спасибо, парни. Я бы предпочел не обновлять и отображать данные, как только они будут доступны в ruby, но я понимаю, что отправка клиенту не может быть выполнена так, как я ее настроил. Кроме того, разве использование кеша не будет работать без обновления страницы?   -  person bcan001    schedule 16.01.2016
comment
Я реализовал это несколько недель назад. Просто отправьте данные обратно клиенту с помощью ActionCable.   -  person Linus Oleander    schedule 30.01.2016


Ответы (2)


Я думаю, что лучше использовать ActionCable и использовать ajax для частичного рендеринга с помощью js.erb, когда вы получаете широковещательное сообщение. то есть в вашем /assets/javascript/channels/comments.js:

this.App = {};

App.cable = ActionCable.createConsumer();

App.comments = App.cable.subscriptions.create('CommentsChannel', {
  received: function(data) {
    this.renderComments(data);
  },

  renderComments: function(data) {
    $.ajax({
      url: "/comments/update_comments"
      data: { data: data } // Depending on how you structure the data you received
    });
  }
});

В вашем контроллере комментариев вы можете делать все, что вам нужно, в методе /comments/update_comments с данными, которые вы получили, чтобы они повлияли на часть, которую вы визуализируете. Допустим, он просто обновит @comments. Затем используйте этот update_comments.js.erb в ваших файлах представления, и он обновит ваш частичный элемент в данном элементе html:

//app/views/comments/update_comments.js.erb
$('#comments_container').html("<%= escape_javascript(render partial: 'comments') %>");

Ваш частичный может быть примерно таким:

<!-- app/views/comments/_comments.html.erb -->
<% @comments.each do |comment| %>
  <p><%= comment.user %>: <%= @comment.message %></p>
<% end %>

Надеюсь, я объяснил себя.

person Sergio Gonzalez    schedule 20.07.2017

Вы можете сделать что-то вроде этого

ActionCable.server.broadcast(
  "comments_#{@comment.id}_channel",
  view: ApplicationController.render(
    partial: 'comments/commment',
    locals: { comment: @comment }
  )
)

И в джс

App.comments = App.cable.subscriptions.create(
  {channel: 'CommentsChannel', id: comment_id }, {
  received: function(data) {
     $('#comments').append(data.view);
  },
person Diego Llamas Velasco    schedule 14.02.2018