Ruby 嵌套形式的动作电缆

Ruby Action Cable for nested form

我有两个模型:post和comment,第二个嵌套在第一个里面。我想为评论创建一个动作电缆。以下是我为 post 制作的方法:它工作得非常好 - 在控制台中显示了 post 的标题和内容。路线:

   resources :posts do
    resources :comments 
  end
  root "posts#index"
  mount ActionCable.server => '/cable'

帖子管理员:

 class PostsController < ApplicationController
before_action :find_post, only: [:show, :update, :edit, :destroy]
after_action :publish_post, only: [:create]
  def publish_post
    ActionCable.server.broadcast "posts_channel", {title: @post.title, content: @post.content}
  end
private
  def find_post
    @post = Post.find(params[:id])
  end
end

posts_channel.rb 的代码:

class PostsChannel < ApplicationCable::Channel
  def subscribed
    stream_from "posts_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

以及 posts_channel.js 的代码:

import consumer from "./consumer"

consumer.subscriptions.create("PostsChannel", {
  connected() {
    console.log('i am post')
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },
  received(data) {
    console.log(data)
    // Called when there's incoming data on the websocket for this channel
  }
});

非常相似的代码我有评论,这里是评论控制器:

class CommentsController < ApplicationController
before_action :find_comment, only: [:destroy]
after_action :publish_comment, only: [:create]
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(params[:comment].permit(:name, :comment, :user_id, :best, :file))
    redirect_to post_path(@post)
  end
  def publish_comment
    ActionCable.server.broadcast "comments_channel", {title: @comment.name, content: @comment.comment}
  end

  private

  def find_comment
    @post = Post.find(params[:post_id])
    @comment = @post.comments.find(params[:id])
  end
end

comments_channel.rb 是完全相同的,但流式传输到 comments_channel.js,这里是 js 通道:

import consumer from "./consumer"

consumer.subscriptions.create("CommentsChannel", {
  connected() {
    console.log('I am comment')
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    console.log(data)
    // Called when there's incoming data on the websocket for this channel
  }
});

我的代码可能有什么问题?我敢肯定,我在 JS 代码上做错了什么,它就是看不到我在 posts 上创建的嵌套表单。正如我所说 - posts 和评论频道非常相同,但有关创建的 post 的数据正在广播到我的控制台,但我的评论不是,即使我在控制器中定义了 post 和哪个评论系统应该看到

设法做到了。我决定为单个 post 创建新频道,这将由 id 决定。所以这是我的 post_channel.rb(!不是 postS_channel.rb):

 class PostChannel < ApplicationCable::Channel
  def subscribed
    stream_from "post_channel_#{params[:post_id]}"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

post_channel 的 Js 文件:

 import consumer from "./consumer"

document.addEventListener('turbolinks:load', () => {

  const element = document.getElementById('post-id');
  const post_id = element.getAttribute('data-post-id');

  consumer.subscriptions.create({channel: "PostChannel", post_id: post_id }, {
    connected() {
      console.log("connected to post №" + post_id)
    },

    disconnected() {
      // Called when the subscription has been terminated by the server
    },

    received(data) {
      $('#comment_name').append('<div class="comment"> <strong>' + data.title + '</strong></div>')
      $('#comment_content').append('<div class="comment">' + data.content + '</div>')
      console.log(data)
    }
  });
})

我的 comments_controller 部分:

 class CommentsController < ApplicationController
  before_action :find_comment, only: [:destroy]
  after_action :publish_comment, only: [:create]

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(params[:comment].permit(:name, :comment, :user_id, :best, :file))
    redirect_to post_path(@post)
  end

  def publish_comment
    ActionCable.server.broadcast("post_channel_#{@comment.post_id}", {title: @comment.name, content: @comment.comment})
  end
  private

  def find_comment
    @post = Post.find(params[:post_id])
    @post_id = @post[:post_id]
    @comment = @post.comments.find(params[:id])
  end
end

我还在我的路线中添加了这一行:

 get '/posts/:id' => 'posts#show'

因此,我所要做的就是指定 post 我的代码应该广播哪个以查看评论。如果有人想使用我的代码 - 小心,它会产生新的错误,你可以通过它得到 'no Post with id=['new']' 错误。