Rails: Action Cable 仅在数据库中保存第一条记录

Rails: Action Cable saves only first record in database

我目前正在努力将 ActionCable 实施到我的应用程序中。我面临的问题是只有第一条消息被保存到数据库中,并且只有第一条消息在视图中被更新。

之后的每条消息都不会保存到数据库中。控制台没有给我太多信息,它只是说 messages_controller.rb line 17 rollback transaction 和下面的几行 Completed 204 No Content in xxxxx.ms

命令提示符

Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-11-10 21:11:33 +0100
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-11-10 21:11:34 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
WebSocket error occurred: Broken pipe
MessagesChannel is transmitting the subscription confirmation
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-11-10 21:11:34 +0100
MessagesChannel is streaming from conversation_8
NotificationsChannel is transmitting the subscription confirmation
NotificationsChannel is streaming from notification_9
Started POST "/conversations/8/messages" for 127.0.0.1 at 2018-11-10 21:11:56 +0100
Processing by MessagesController#create as JS
  Parameters: {"utf8"=>"✓", "message"=>{"context"=>"jhhjhkh", "user_id"=>"9"}, "commit"=>"Absenden", "conversation_id"=>"8"}
  User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 9], ["LIMIT", 1]]
  ↳ C:/RailsInstaller/Ruby2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
  Conversation Load (0.0ms)  SELECT  "conversations".* FROM "conversations" WHERE "conversations"."id" = ? LIMIT ?  [["id", 8], ["LIMIT", 1]]
  ↳ app/controllers/messages_controller.rb:31
   (0.0ms)  begin transaction
  ↳ app/controllers/messages_controller.rb:17
  User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 9], ["LIMIT", 1]]
  ↳ app/controllers/messages_controller.rb:17
  Message Exists (0.0ms)  SELECT  1 AS one FROM "messages" WHERE "messages"."context" = ? LIMIT ?  [["context", "jhhjhkh"], ["LIMIT", 1]]
  ↳ app/controllers/messages_controller.rb:17
  Message Exists (0.0ms)  SELECT  1 AS one FROM "messages" WHERE "messages"."conversation_id" = ? LIMIT ?  [["conversation_id", 8], ["LIMIT", 1]]
  ↳ app/controllers/messages_controller.rb:17
  Message Exists (0.0ms)  SELECT  1 AS one FROM "messages" WHERE "messages"."user_id" = ? LIMIT ?  [["user_id", 9], ["LIMIT", 1]]
  ↳ app/controllers/messages_controller.rb:17
   (0.0ms)  rollback transaction
  ↳ app/controllers/messages_controller.rb:17
No template found for MessagesController#create, rendering head :no_content
Started GET "/cable" for 127.0.0.1 at 2018-11-10 21:12:11 +0100
Completed 204 No Content in 13166ms (ActiveRecord: 0.0ms)


Started GET "/cable" for 127.0.0.1 at 2018-11-10 21:12:11 +0100
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-11-10 21:12:11 +0100
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-11-10 21:12:11 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
WebSocket error occurred: Broken pipe
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-11-10 21:12:11 +0100
MessagesChannel is transmitting the subscription confirmation
MessagesChannel is streaming from conversation_8
NotificationsChannel is transmitting the subscription confirmation
NotificationsChannel is streaming from notification_9
Started GET "/" for 127.0.0.1 at 2018-11-10 21:12:29 +0100
Processing by PagesController#home as HTML
  Rendering pages/home.html.erb within layouts/application
  Rendered shared/_footer.html.erb (4.0ms)
  Rendered pages/home.html.erb within layouts/application (132.0ms)
  User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 9], ["LIMIT", 1]]
  ↳ app/views/shared/_navbar.html.erb:21
  Rendered shared/_navbar.html.erb (176.0ms)
  Rendered shared/_message.html.erb (0.0ms)
Completed 200 OK in 2052ms (Views: 1943.4ms | ActiveRecord: 8.0ms)

我的消息控制器

class MessagesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_conversation

  def index
    if current_user == @conversation.sender || current_user == @conversation.recipient
      @other = current_user == @conversation.sender ? @conversation.recipient : @conversation.sender
      @messages = @conversation.messages.order("created_at DESC")
    else
      redirect_to conversations_path, alert: "You don't have permission."
    end
  end

  def create
    @message = @conversation.messages.new(message_params)
    @messages = @conversation.messages.order("created_at DESC")
    if @message.save
      ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
    end
end


  private

  def render_message(message)
    self.render(partial: 'messages/message', locals: {message: message})
  end

  def set_conversation
    @conversation = Conversation.find(params[:conversation_id])
  end

  def message_params
    params.require(:message).permit(:context, :user_id)
  end
end

这是因为 @message 的验证失败。因此,将您的 create 操作更新为类似这样的内容。

def create
    @message = @conversation.messages.new(message_params)
    @messages = @conversation.messages.order("created_at DESC")
    if @message.save
      ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
    else
      Rails.logger.info "Errors: #{@message.errors.full_messages}"
    end
end

观察else部分,它会将验证错误打印到控制台。在理想情况下,您会希望向用户显示这些错误消息。

Also, you can use if @message.save! this will create an exception. @message.save just returns true or false