Как сначала визуализировать партиал в broadcats_to, а затем перенаправить (AbstractController :: DoubleRenderError) - PullRequest
0 голосов
/ 14 сентября 2018

Я новичок в Rails и пытался использовать Action Cable для обновления клиентов при сохранении новой записи в базе данных.

Для этого у меня есть posts_controller.rb:

  # POST /posts
  # POST /posts.json
  def create
    @post = Post.new(post_params)
    picture = params[:post][:picture]
    respond_to do |format|
      if @post.save
        @post.picture.attach(picture) if picture.present?
        PostsChannel.broadcast_to @post, html: render(partial: 'post', locals: { post: @post }) #<--- render
        format.html { redirect_to posts_url, notice: 'Post was successfully created.' } #<--- redirect
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

А _post.html.erb:

<div class="cd-timeline__block js-cd-block">
  <div class="cd-timeline__img cd-timeline__img--picture js-cd-img">
    <p>?</p>
  </div>

  <div class="cd-timeline__content js-cd-content">
    <%= image_tag post.picture.variant(resize: '400x400') %>
    <p><%= post.text %></p>
    <span class="cd-timeline__date"><%= post.created_at.strftime('%d/%m/%Y %T') %></span>
  </div>
</div>

Это заканчивается ошибкой AbstractController::DoubleRenderError из-за частичного рендеринга и перенаправления. Дело в том, что я понятия не имею, как это сделать иначе. Я не хочу генерировать HTML-файл в JS-файле, как видно из нескольких примеров кода (у меня будет дублирование кода для моего пост-шаблона). Я искал другие примеры, но ничто не помогло мне.

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

Любой совет?

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Хорошо, так что я получил это работает!:)

Существует функция rails, которая делает именно то, что я хочу: render_to_string , которая не отправляет HTTP-ответ.У меня были некоторые проблемы с веб-сокетами, поэтому я установил Redis +, изменив способ вещания, и теперь все работает нормально!

Для записей вот все:

# config/routes.rb
Rails.application.routes.draw do
  resources :posts
  mount ActionCable.server => '/cable'
end

-

# config/cable.yml
development:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>

-

# app/channels/posts_channel.rb
class PostsChannel < ApplicationCable::Channel
  def subscribed
    stream_for 'post'
  end
end

-

// app/assets/javascripts/channels/posts.js
App.cable.subscriptions.create('PostsChannel', {
  received: function({ html }) {
    $("#timeline-container").prepend(html);
  }
});

-

<!-- app/views/posts/_post.html.erb -->
<div class="cd-timeline__block js-cd-block">
  <div class="cd-timeline__img cd-timeline__img--picture js-cd-img">
    <p>?</p>
  </div>

  <div class="cd-timeline__content js-cd-content">
    <%= image_tag post.picture.variant(resize: '400x400') %>
    <p><%= post.text %></p>
    <span class="cd-timeline__date"><%= post.created_at.strftime('%d/%m/%Y %T') %></span>
  </div>
</div>

-

# POST /posts
# POST /posts.json
def create
  @post = Post.new(post_params)
  picture = params[:post][:picture]
  respond_to do |format|
    if @post.save
      @post.picture.attach(picture) if picture.present?
      ActionCable.server.broadcast 'posts:post', html: render_to_string(partial: 'post', locals: { post: @post })
      format.html { redirect_to posts_url, notice: 'Post was successfully created.' }
      format.json { render :show, status: :created, location: @post }
    else
      format.html { render :new }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end
0 голосов
/ 14 сентября 2018

Можете ли вы попробовать переместить рендер в обратный вызов after_action? у вас будет доступ к @post, чтобы вы могли позвонить @post.valid? и узнать, нужно ли вам это транслировать. Я не уверен, что это работает, но вы можете попробовать.

Я бы не стал транслировать рендер частичного. Возможно, было бы быстрее транслировать @post как json и обновить представление с помощью клиентской стороны javascript.

РЕДАКТИРОВАТЬ: попробуйте с render_to_string https://apidock.com/rails/AbstractController/Rendering/render_to_string

Он отображает представления и партиалы, но не устанавливает тело ответа на запросы. Только что попробовал локально, и он работает с двумя рендерами.

...