【问题标题】:How to first render a partial in broadcasts_to and then redirect (AbstractController::DoubleRenderError)如何首先在 broadcasts_to 中渲染部分内容然后重定向(AbstractController::DoubleRenderError)
【发布时间】:2018-09-14 01:49:26
【问题描述】:

我是 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。问题是我不知道如何做到这一点。我不想在 JS 文件中生成 HTML,因为看到的是一些代码示例(我的帖子模板会有代码重复)。我一直在寻找其他示例,但没有任何帮助。

herehere 讨论了同样的问题,但我不知道如何使用 flash 来获得我想要的。

有什么建议吗?

【问题讨论】:

    标签: ruby-on-rails ruby actioncable


    【解决方案1】:

    您可以尝试将渲染移至 after_action 回调吗?您将可以访问@post,因此您可以致电@post.valid? 以了解您是否需要广播。我不确定这是否有效,但您可以尝试一下。

    不过,我不会广播部分渲染。也许将@post 广播为json 并使用javascript 客户端更新视图会更快。

    编辑:尝试render_to_string https://apidock.com/rails/AbstractController/Rendering/render_to_string

    它呈现视图和部分,但它不设置请求的响应正文。刚刚在本地尝试过,它适用于两个渲染。

    【讨论】:

    • 刚刚尝试在 after_action 中移动广播,但仍然出现 DoubleRenderError。正如我所说,在 ruby​​ 服务器端和 js 客户端都有模板让我很恼火。如果我修改一个,我也必须修改另一个。另一种选择是只显示带有 JS 的帖子,并且只有 js 模板。但这对我来说感觉不对。
    • 我也找到了 ;)
    【解决方案2】:

    好的,所以我开始工作了! :)

    有一个 rails 函数可以完全满足我的要求:render_to_string 不发送 http 响应。 我在使用 websockets 时遇到了一些问题,所以我安装了 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
    

    【讨论】:

      猜你喜欢
      • 2019-10-10
      • 1970-01-01
      • 2015-11-27
      • 2015-10-26
      • 2014-07-02
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多