[Ruby] DM function implementation

3 minute read

I will put it together for myself.

Required table

users
User table

rooms
A place to have a chat room

entries
A table that manages users entering the chat room

messages
Table to manage messages

Implementation

Modeling

$ rails g model room name:string
$ rails g model entry user:references room:references
$ rails g model message user:references room:references content:text
$ rails db:migrate

user.rb


class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :messages, dependent: :destroy
  has_many :entries, dependent: :destroy
end

entry.rb


class Entry < ApplicationRecord
  belongs_to :user
  belongs_to :room
end

room.rb


class Room < ApplicationRecord
  has_many :messages, dependent: :destroy
  has_many :entries, dependent: :destroy
end

message.rb


class Message < ApplicationRecord
  belongs_to :user
  belongs_to :room
end



Controller creation

$ rails g controller users index show
$ rails g controller rooms
$ rails g controller messages

routes.rb


resources :users, only: [:show,:edit,:update]
resources :messages, only: [:create]
resources :rooms, only: [:create,:show]

users_controller.rb


class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    # current_Find user from the Entries table
    @currentUserEntry = Entry.where(user_id: current_user.id)
    #Find the user to send the DM from the Entries table
    @userEntry = Entry.where(user_id: @user.id)

    if @user.id != current_user.id
      #with [email protected] out each user's Entries one by one and check if the two rooms already exist
      @currentUserEntry.each do |cu|
        @userEntry.each do |u|
          #If a room for 2 people already exists
          if cu.room_id == u.room_id
            @isRoom = true
            #room_Extract id
            @roomId = cu.room_id
          end
        end
      end

      #If there is no room for 2 people
      unless @isRoom
        #Create new room and entry
        @room = Room.new
        @entry = Entry.new
      end
    end
  end
end

ruby:users/show.html.slim


  - if @user.id != current_user.id

    #Must be following each other
    - if (current_user.following? @user) && (@user.following? current_user)

      #If you already have a room (you have previously exchanged DMs)
      - if @isRoom == true
         #Enter the room
         =link_to room_path(@roomId) do
           i.fas.fa-envelope

      #If there is no room (new DM)
      - else
        #Send data to two models, Room and Entry
        = form_with @room, local: true do |f|
          = fields_for @entry do |e|
            #Entry is user_Because you need to send the [email protected] id
            = e.hidden_field :user_id, value: @user.id
          #This time, the button is used for the link because the icon is used._Use tag. Normally f.OK with submit
          = button_tag type: 'submit' do
            i.fas.fa-envelope

rooms_controller


class RoomsController < ApplicationController

  def create
    @room = Room.create
    # current_user Entry
    @entry1 = Entry.create(room_id: @room.id, user_id: current_user.id)
    #Entry (users) on the receiving side of DM/user in show_room is passed because id is passed_I'm picking up the id and merging it)
    @entry2 = Entry.create((entry_params).merge(room_id: @room.id))
    redirect_to room_path(@room)
  end

  def show
    @room = Room.find(params[:id])
    #current in entries table_user.Check if there is a chat room associated with id
    if Entry.where(user_id: current_user.id,room_id: @room.id).present?
      @messages = @room.messages
      @message = Message.new
      #Substitute to display chat room user information
      @entries = @room.entries
    else
      redirect_back(fallback_location: root_path)
    end
  end

  private
    def entry_params
      params.require(:entry).permit(:user_id, :room_id)
    end

end

ruby:rooms/show.html.slim


.row
  .col-lg-2
  .col-lg-8.frame-notification
    <hr>
    #Show list if there is a message
    - if @messages.present?
      - @messages.each do |message|
        .row.balloon5
          #This time, I want to display my message on the right side, so the following conditional branch
          - if current_user.name == message.user.name
            .col-lg-12.text-right
              .chatting
                .say
                  = message.content
                <br>
                small= message.created_at.to_s(:datetime_jp)
          - else
            .col-lg-2.text-center
              = attachment_image_tag message.user, :image, format: 'jpeg', fallback: "noimage.png ", size: "50x40"
              small= link_to message.user.name, user_path(message.user), class: "d-block mt-1"
              <br>
            .col-lg-10.text-left
              .chatting
                .says
                  p= message.content
                <br>
                small= message.created_at.to_s(:datetime_jp)
        <hr>
    - else
There are no p messages.

    .row
      .col-lg-2
      .col-lg-8.text-center
        = form_with model: @message, local: true do |f|
          = f.text_field :content, placeholder: "Please enter a message" , size: 50
          = f.hidden_field :room_id, value: @room.id
          = f.submit "Post", class: 'btn btn-outline-secondary btn-sm ml-2'

messages_controller.rb


class MessagesController < ApplicationController

  def create
    #room sent in form_id and current_user.Check if the data with id is in Entry
    if Entry.where(user_id: current_user.id, room_id: params[:message][:room_id]).present?
      #content and room_Since the id is sent in form, user_Merge ids to compose new message
      @message = Message.create((message_params).merge(user_id: current_user.id))
      redirect_back(fallback_location: root_path)
    else
      flash[:alert] = "Failed to send the message."
      redirect_back(fallback_location: root_path)
    end
  end

  private
    def message_params
      params.require(:message).permit(:user_id, :content, :room_id)
    end

end

**Complete! ** **