Reputation: 2900
I used this guide as a starting point for creating a messaging system from scratch. I had to modify these to handle messages between User
and AdminUser
. For some reason, whenever I now try to create a new conversation by clicking in my view the following link:
<li><%= link_to admin.email, conversations_path(sendable_id: current_user.id, recipientable_id: admin.id), method: :post %></li>
I encounter the error:
ActionController::ParameterMissing (param is missing or the value is empty: conversation Did you mean? controller authenticity_token action recipientable_id):
Params are:
=> #<ActionController::Parameters {"_method"=>"post", "authenticity_token"=>"pHmi9kWBLSc5QSJUPQxfNsqSR1fqWCSCBqEVgRMljhgrxB9g4M0ClsdEi2hBLCTjrLLl774T-mnyK8m40LFhNA", "recipientable_id"=>"1", "sendable_id"=>"2", "controller"=>"conversations", "action"=>"create"} permitted: false>
I am directed to the params.permit line in my controller:
class ConversationsController < BaseController
def index
@users = User.all
@admins = AdminUser.all
@conversations = Conversation.all
end
def create
@conversation = if Conversation.between(params[:sendable_id], params[:recipientable_id]).present?
Conversation.between(params[:sendable_id], params[:recipientable_id]).first
else
Conversation.create!(conversation_params)
end
redirect_to conversation_messages_path(@conversation)
end
private
def conversation_params
params.require(:conversation).permit(:sendable_id, :recipientable_id)
end
end
If I remove require(:conversation)
I'll get an error:
Validation failed: Sendable must exist, Recipientable must exist
Models:
class User < ApplicationRecord
has_many :conversations, as: :sendable
has_many :conversations, as: :recipientable
end
class AdminUser < ApplicationRecord
has_many :conversations, as: :sendable
has_many :conversations, as: :recipientable
end
class Conversation < ApplicationRecord
belongs_to :sendable, polymorphic: true
belongs_to :recipientable, polymorphic: true
has_many :messages, dependent: :destroy
validates :sendable_id, uniqueness: { scope: :recipientable_id }
end
class Message < ApplicationRecord
belongs_to :conversation
belongs_to :messageable, polymorphic: true
validates_presence_of :body
end
schema:
create_table "conversations", force: :cascade do |t|
t.string "sendable_type"
t.bigint "sendable_id"
t.string "recipientable_type"
t.bigint "recipientable_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["recipientable_type", "recipientable_id"], name: "index_conversations_on_recipientable"
t.index ["sendable_type", "sendable_id"], name: "index_conversations_on_sendable"
end
Upvotes: 0
Views: 670
Reputation: 7878
You need to help Rails understand which polymorphic models you are referencing; if you only provide ids it fails because Rails also needs the polymorphic type (remember: the type is mandatory so Rails can make the link to the actual table. In your case there are two possible types User and AdminUser)
Simply provide the polymorphic types and also add them to the conversation_params
method. From looking at your code I'm guessing this is what you're after:
<li><%= link_to admin.email, conversations_path(sendable_id: current_user.id, sendable_type: 'User', recipientable_id: admin.id, recipientable_type: 'AdminUser'), method: :post %></li>
Upvotes: 1