0

I'm currently struggling to implement ActionCable into my application. The problem that I'm facing is that only the first message is saved into the databse and only the first message is updated in the view.

Every message afterwards isn't saved into the db. The console gives me not much information, it just says messages_controller.rb line 17 rollback transaction and few lines below Completed 204 No Content in xxxxx.ms

Command Prompt

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)

My messages controller

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
klasarn
  • 129
  • 1
  • 12
  • it seems like a model validation failure. change `save` to `save!`, that will raise an exception and will show the reason for transaction rollback. – PGill Nov 11 '18 at 07:38

1 Answers1

0

This is because of validation failure for @message. So, Update your create action to something like this.

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

Observe the else part, It will print validation errors to console. In an ideal scenario, you would want to show these error messages to users.

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

Abhilash Reddy
  • 1,499
  • 1
  • 12
  • 24