Rails 5 Render view/partial с Active Job с Presenter

Я новичок в Rails, и я пробовал Active Job и Action Cable, а также Presenter, и я искал повсюду, но не смог понять это.

поэтому мой вопрос заключается в том, есть ли способ использовать презентатор в партиале и отображать его вне контроллера (например, в ActiveJob)?

ниже то, что я хочу достичь:

У меня есть система сообщений (больше похожая на электронную почту) с контроллером разговоров и контроллером сообщений. Чего я хочу добиться, так это того, что когда кто-то начинает новый разговор, если получатель находится на индексной странице разговора, новый разговор автоматически добавляется к их индексному представлению (например, в электронных письмах) с помощью ActionCable.

Итак, мой разговор.рб

    class Conversation < ApplicationRecord
    has_many :messages, dependent: :destroy
    after_create_commit { ConversationBroadcastJob.perform_later(self) }

разговор_broadcast_job.rb

    class ConversationBroadcastJob < ApplicationJob
     queue_as :default

       def perform(conversation)
        ActionCable.server.broadcast "conversations:#{conversation.receiver_id}",
                              {convo: render_conversation(conversation)}
      end

      private

      def render_conversation(conversation)
        ConversationsController.render(partial: 'conversations/conversation',
                     locals: {conversation: conversation, var: 'not'})
      end

    end

и мой _conversation.html.erb, я использовал Presenter, следуя этому выпуску RailCast

    <% present conversation do |conversation_presenter| %>

    <div class="conversation <%=conversation_presenter.css(var)%>"
         id="conversation_<%= conversation.id %>"
         data-sender-id='<%= conversation_presenter.sender_id%>'>

      <%=conversation_presenter.avatar%>

      <div class="conversation-counterpart-name conversation-info truncate">
        <%=conversation_presenter.name(var) %>
      </div>


      <div class='conversation-subject conversation-info truncate'>
        <%=link_to conversation_messages_path(conversation),
                                      class:'link-gray truncate' do |n|%>
          <%=conversation_presenter.subject %>
           <div class='last-message truncate'>
            <%=conversation_presenter.last_message%>
          </div>
        <% end %>
      </div>

      <div class="conversation-date conversation-info">
        <%=conversation_presenter.last_date%>
      </div>

    </div>

    <% end %>

Настоящий метод определен в ApplicationHelper.

      def present(object, klass = nil)
        klass ||= "#{object.class}Presenter".constantize
        presenter = klass.new(object, self)
        yield presenter if block_given?
        presenter
      end

разговор_представитель.rb

    class ConversationPresenter < BasePresenter

      presents :conversation
      delegate :subject, to: :conversation


      def name(var)
        if conversation.sender_id == var.id
          conversation.receiver.name
        else
          conversation.sender.name
        end
      end

      def last_date
        if conversation.last_msg.nil?
          conversation.render_date
        else
          conversation.last_msg.render_date
        end
      end

      def last_message
        conversation.last_msg.content unless conversation.last_msg.nil?
      end

      def avatar
        h.image_tag('avatar.svg', size: 30, class:'conversation-        counterpart-avatar')
      end

      def css(var)
        "unread" unless
        conversation.read || (!conversation.last_msg.nil? &&     conversation.last_msg.wrote_by(var))
      end

      def sender_id
        if conversation.last_msg.nil?
          conversation.sender_id
        else
          conversation.last_msg.author_id
        end
      end

    end

Проблема начинается отсюда, частичное не будет отображаться в ActiveJob из-за ведущего разговора, который я предполагаю. Итак, мой вопрос в том, можно ли вообще использовать презентер с рендерингом вне контроллера?

Пожалуйста, дайте мне знать, если вам нужна информация о других частях моих кодов.

Спасибо!


person Rosalie    schedule 19.03.2017    source источник


Ответы (3)


Я использовал следующий код, чтобы запустить его из ActiveJob:

ApplicationController.new.render_to_string(
  :template => 'users/index',
  :layout => 'my_layout',
  :locals => { :@users => @users }
)

Извлечено из https://makandracards.com/makandra/17751-render-a-view-from-a-model-in-rails

person elmerfreddy    schedule 18.02.2018

попробуйте использовать

ConversationsController.render -> ApplicationController.renderer.render

это помогает мне один раз.

  def render_conversation(conversation)
       renderer=ApplicationController.renderer.new
       renderer.render(partial: 'conversations/conversation',
                     locals: {conversation: conversation, var: 'not'})

  end
person Валерий Васильев    schedule 20.03.2017
comment
Не могли бы вы дать больше информации? Я пытался, но это не сработало ConversationsController.render -> ApplicationController.renderer.render {(partial: 'диалог/диалог', locals: {диалог: беседа, var: 'не'})} - person Rosalie; 20.03.2017
comment
@ Розали, у меня такая же проблема, когда я пытаюсь выполнить рендеринг с заданий. Обычно задание наследуется от ApplicationJob(ActiveJob::Base). Но рендеринг - это метод ApplicationController. поэтому для рендеринга с задания вам нужно изменить свой Conversationscontroller на aplicationcontroller.renderer. я положил пример в ответ. - person Валерий Васильев; 20.03.2017
comment
@Rosalie, попробуй поставить какой-нибудь журнал. видеть были - проблема - person Валерий Васильев; 20.03.2017

Ниже работает в Rails 5:

ApplicationController.render(
  :template => 'users/index',
  :layout => 'my_layout',
  :assigns => { users: @users }
)

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

я использовал в работе (jobs/invoice_job.rb)

invoice_obj = Invoice.first
# Process the pdf_attachement in any way you want
pdf_attachement = WickedPdf.new.pdf_from_string(
      ApplicationController.render(template: 'invoices/invoice_pdf.html.erb', layout: 'layouts/pdf.html.haml', assigns: { invoice: invoice })
    )

используйте его в представлении, как показано ниже: (views/invoices/invoice_pdf.html.erb)

<%
@invoice = assigns[:invoice]
%>
<%= render 'invoices/invoice_pdf_template' %> <!-- generate your pdf html -->

макет в формате pdf: (layouts/pdf.html.haml)

!!!
%html
  %head
    %title RailsWickedPdf
    = wicked_pdf_stylesheet_link_tag "application", :media => "all"
    = wicked_pdf_stylesheet_link_tag "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css", media: "all"
    = wicked_pdf_javascript_include_tag "application"
    = csrf_meta_tags
  %body
    = yield

Подробнее см. здесь.

person Ravistm    schedule 15.11.2019