1

Have a recipient and sender, both of the same class(Message) for a messaging system in rails. Want to set the params for both i.e. if user creates a message sender by default is the user_id and recipient will be the contact selected from the users contact list.

Currently the database is only receiving a user_id to the recipient_id column which is wrong and should be to sender_id column. Sender_id receives nothing.

After reading, some say not to amend the params as this is bad practice. So set a hidden field in the message view (like the body and title) yet this isn't pushing in to the database.

Two questions, is this process an appropriate rails practice? (ask this as new to rails) If not: can you advise another path or direction? If so: any ideas/thoughts why this isn't saving in to the database?

user model

class User < ActiveRecord::Base

  has_many :messages, class_name: "Message", foreign_key: "recipient_id"
  has_many :sent_messages, class_name: "Message", foreign_key: "sender_id"

  has_many :contacts, dependent: :destroy
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  validates_presence_of :firstname, allow_blank: false
  validates_presence_of :surname, allow_blank: false

end

message model

class Message < ActiveRecord::Base

  belongs_to :sender, class_name: "User", foreign_key: "sender_id"
  belongs_to :recipient, class_name: "User", foreign_key: "recipient_id"

    validates_presence_of :body, :title
end

Messages controller

class MessagesController < ApplicationController

  before_action :message, only: [:show]
  before_action :authenticate_user!

  def index
    @messages = current_user.messages
  end

  def new
    @message = Message.new
  end

  def create
    current_user.messages.create(message_params)
    redirect_to '/messages'
  end

  def show
  end

  private

  def message_params
    params.require(:message).permit(:title, :body, :sender_id, :recipient_id)
  end

  def message
    @message = Message.find(params[:id])
  end

end

message/new view

<%= form_for @message do |f| %>
     <%= hidden_field_tag :sender_id, current_user.id %>
     <%= f.text_field :title %>
     <%= f.text_field :body %>
     <%= f.submit %>
<% end %>

schema

ActiveRecord::Schema.define(version: 20160517131719) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "contacts", force: :cascade do |t|
    t.string   "firstname"
    t.string   "surname"
    t.string   "email"
    t.integer  "phone"
    t.datetime "created_at",         null: false
    t.datetime "updated_at",         null: false
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.integer  "image_file_size"
    t.datetime "image_updated_at"
    t.integer  "user_id"
  end

  add_index "contacts", ["user_id"], name: "index_contacts_on_user_id", using: :btree

  create_table "messages", force: :cascade do |t|
    t.string   "title"
    t.text     "body"
    t.integer  "sender_id"
    t.integer  "recipient_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet     "current_sign_in_ip"
    t.inet     "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.string   "firstname"
    t.string   "surname"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree

  add_foreign_key "contacts", "users"
end
blastoff
  • 31
  • 7
  • Not an exact answer, but there's a great tutorial here: https://www.youtube.com/watch?v=lZjMQsVdc_w#t=2m30s – stevec Oct 22 '20 at 08:01

2 Answers2

0

Try changing your form to this:

<%= form_for @message do |f| %>
  <%= f.hidden_field :sender_id, value: current_user.id %> 
  <%= f.text_field :title %>
  <%= f.text_field :body %>
  <%= f.submit %>
<% end %>
Graham Slick
  • 6,692
  • 9
  • 51
  • 87
0

Currently the database is only receiving a user_id to the recipient_id column which is wrong and should be to sender_id column.

In your create action, you have current_user.messages.create(message_params). This creates a message record in the DB with the foreign key's(i.e, recipient_id in your case) value with the parent's(user) id. This is the reason, the recipient_id gets the value of user's id.

Sender_id receives nothing.

This is because the hidden_field set for sender_id is not wrapped with the form builder instance. You need to change

<%= hidden_field_tag :sender_id, current_user.id %>

to

<%= f.hidden_field :sender_id, current_user.id %>
Pavan
  • 33,316
  • 7
  • 50
  • 76
  • tks @Pavan that is interesting. So this is set in the model of User? but why doesn't it produce this for the sender_id as well then as both sender_id and recipient_id are set in User model? – blastoff May 17 '16 at 16:44
  • @blastoff This is because `sender_id` is ***not*** the `foreign_key` for `messages`. It is the `foreign_key` for `sent_messages`. – Pavan May 17 '16 at 16:46