Search code examples
ruby-on-railsmessaging

Rails custom message system, conversation is not created properly


So I created a custom message system based on https://www.sitepoint.com/build-a-messaging-system-with-rails-and-actioncable/

It worked great until I encountered a bug where it could not create new conversations properly. (Conversation is named insconversation in my code)

class PersonalMessagesController
...
  def create
    @insconversation ||= Insconversation.create(author_id: current_user.id, //This part seems to be having issues
                                      receiver_id: @receiver.id)
    @personal_message = current_user.personal_messages.build(personal_message_params)
    @personal_message.insconversation_id = @insconversation.id
    @personal_message.save!

    flash[:success] = "Your message was sent!"
   redirect_to insconversation_path(@insconversation)
  end
...

The message itself is saved into the Mysql database, but it's parent "insconversation_id" is left null, similarly on the "insconversation" table no new conversation is added. I used render :text => and insconversation and it's id are both null, (as in failed to be created).

The errror message I recived is at the redirect_to part No route matches {:action=>"show", :controller=>"insconversations", :id=>nil} missing required keys: [:id]

And the personal message view

view/Personal_Message
<h1>New message to <%= @receiver.name %></h1>   //receiver is properly identified

<%= form_for @personal_message do |f| %>
  <%= hidden_field_tag 'receiver_id', @receiver.id %>

  <%= f.label :body %>
  <%= f.text_area :body, size: "60x3", required:true %>

  <%= f.submit %>

<% end %>

conversation controller

class InsconversationsController < ApplicationController
  before_action :set_insconversation, except: [:index]
  before_action :check_participating!, except: [:index]

  def index
    @insconversations = Insconversation.participating(current_user).order('updated_at DESC')
  end

  def show
    @insconversation = Insconversation.find_by(id: params[:id])
    @personal_message = PersonalMessage.new
  end

  private

  def set_insconversation
    @insconversation = Insconversation.find_by(id: params[:id])
  end

  def check_participating!
    redirect_to root_path unless @insconversation && @insconversation.participates?(current_user)
  end
end

Edit:

I just checked the SQL log

 Insconversation Exists (0.2ms)  SELECT  1 AS one FROM `insconversations` WHERE `insconversations`.`author_id` = 2 AND `insconversations`.`receiver_id` = 3 LIMIT 1
   (0.2ms)  ROLLBACK
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `personal_messages` (`body`, `user_id`, `created_at`, `updated_at`) VALUES ('8', 2, '2017-04-24 00:31:11', '2017-04-24 00:31:11')

The system seems to think the Inconversation already exists.


Solution

  • The ID on a model is set automatically by Rails so the part of your code that you comment that you're having issues with is not the actual problem. The issue is with the line:

       redirect_to insconversation_path(@insconversation)
    

    The message states that you're missing the params for insconversation ID. You just need to make a slight adjustment to this line to get the ID.

    redirect_to insconversation_path(@insconversation.id)
    

    Or you can just do

    redirect_to @insconversation
    

    and Rails will infer the rest.