[RUBY] Rails ~ Understanding the message function ~

Decipher the message function

Target

Understand the meaning of the code for message features that you do not fully understand. Reference site "Let's make Rails send DM (direct message)" https://qiita.com/nojinoji/items/2b3f8309a31cc6d88d03

image

Create a user model with devise, and you will be able to exchange messages between users.

** User model: User information Room model: This time, an image of two users entering the chat room Entry model: Which User belongs to which Room Message model: What message the User sent in which room **

Contents

First, make an association. user.rb

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

entry.rb
class Entry < ApplicationRecord
  belongs_to :user
  belongs_to :room
end

room.rb

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

message.rb

message.rb
class Message < ApplicationRecord
  belongs_to :user
  belongs_to :room
end

This is the same as it is, so I will omit it

Then create a controller

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

users_controller.rb

class UsersController < ApplicationController
  before_action :authenticate_user!, :only => [:show]
  def index
    @users=User.all
  end

  def show
    @user=User.find(params[:id])
    @currentUserEntry=Entry.where(user_id: current_user.id)
    @userEntry=Entry.where(user_id: @user.id)
unless @user.id == current_user.id
  @currentUserEntry.each do |cu|
    @userEntry.each do |u|
      if cu.room_id == u.room_id then
        @isRoom = true
        @roomId = cu.room_id
      end
    end
  end
  unless @isRoom
    @room = Room.new
    @entry = Entry.new
  end
end
   
    @user=User.find(params[:id])
    @currentUserEntry=Entry.where(user_id: current_user.id)
    @userEntry=Entry.where(user_id: @user.id)

Read the show part. First of all, this part, but at the top, the information of user.id that was pressed when requesting user # show is searched by the find method and assigned to the instance variable @user. The second line uses the where method to assign the result of searching from the id of current_user to @currentUserEntry. The result of searching from the id of the instance variable user searched in the first line using the where method in the third line is assigned to @UserEntry. Two variables are defined here. And when the room is created, both the currently logged in user and the user who pressed "to chat" need to be recorded in the Entries table, so the where method is looking for that user. is there. At first I was wondering why I was using the where method, but this is just to check if the two user.ids specified in the entry table are registered, so if it is not registered, use the find method etc. If you use it, you will get an error if it cannot be found.

unless @user.id == current_user.id
  @currentUserEntry.each do |cu|
    @userEntry.each do |u|
      if cu.room_id == u.room_id then
        @isRoom = true
        @roomId = cu.room_id
      end
    end
  end
  unless @isRoom
    @room = Room.new
    @entry = Entry.new
  end
end

Here, use the unless statement to check if @user and current_user are the same. If they are different, fill in the code below. Pass the information of two variables @currentUserEntry and @userEntry as block arguments, and check if the same Room_id exists in the two arguments. Substitute true for @isRoom, if any. The room_id of current_user is assigned to @roomId. If the same room_id is not found in the two entries, we have added a process to create a new room and entry.

<% unless @user.id == current_user.id %>
          <% if @isRoom == true %>
            <p><a href="/rooms/<%= @roomId %>">send a message</a>
          <% else %>
            <%= form_for @room do |f| %>
              <%= fields_for @entry do |e| %>
                <%= e.hidden_field :user_id, :value=> @user.id %>
              <% end %>
            <%= f.submit "send a message" %>
            <% end %>
       <% end %>
  <% end %>

Then look at the view. Like the controller, @isRoom is used to make a conditional branch when a chat room has already been created and when it has not been created. When @isRoom is true, you can make a button appear in the chat and move to the chat that has already been created. Also, if the chat room has not been created yet @room = Room.new @entry = Entry.new Parameters must be sent to. Here, the @room of the parent model is the form_for instance variable, and the @entry is the fields_for instance variable. Now you're ready to save to the Rooms table.

rooms_controller.rb

class RoomsController < ApplicationController
  before_action :authenticate_user!
  def create
    @room = Room.create
    @entry1 = Entry.create(:room_id => @room.id, :user_id => current_user.id)
    @entry2 = Entry.create(params.require(:entry).permit(:user_id, :room_id).merge(:room_id => @room.id))
    redirect_to "/rooms/#{@room.id}"
  end

  def show
    @room = Room.find(params[:id])
    if Entry.where(:user_id => current_user.id, :room_id => @room.id).present?
      @messages = @room.messages
      @message = Message.new
      @entries = @room.entries
    else
      redirect_back(fallback_location: root_path)
    end
  end
end

Next, understand the rooms controller.

def create
    @room = Room.create
    @entry1 = Entry.create(room_id: @room.id, user_id: current_user.id)
    @entry2 = Entry.create(params.require(:entry).permit(:user_id, :room_id).merge(room_id: @room.id))
    redirect_to "/rooms/#{@room.id}"
end

create creates a new Room and Entry. Entry registers two users, current_user and show user. Create Room_id with @room = Room.create.

@entry1 = Entry.create(room_id: @room.id, user_id: current_user.id) Save the id of current_user and the id of the newly created room in (Entry information of current_user)

@entry2=Entry.create(params.require(:entry).permit(:user_id, :room_id).merge(room_id: @room.id)) Assign the @user information assigned by user / show to id. Merge and register the new: room_id there. And at the same time as create, redirect so that the chat room opens.

def show
  @room = Room.find(params[:id])
  if Entry.where(user_id: current_user.id,room_id: @room.id).present?
    @messages = @room.messages
    @message = Message.new
    @entries = @room.entries
  else
    redirect_back(fallback_location: root_path)
  end
end

Since show needs to display the corresponding chat room first, search for params with the find method. In the Entries table of the searched room, find the id of the currently logged-in user and the id of the chat room associated with it with the where method, and check if the record exists. If the condition is false, use redirect_back, which is a description to return to the previous page. If the condition is true, substitute the description @ room.messages using the association in @messages to display the message associated with the id of the chat room in the Message table.

Also, when creating a new message, in order to create an instance of the message, do Message.new and assign it to @message.

Then, in order to display information such as the user's name in rooms / show.html.erb, put @ room.entries in an instance variable called @entries and get the user_id information of the Entries table.

messages_controller.rb
class MessagesController < ApplicationController
  before_action :authenticate_user!, :only => [:create]

  def create
    if Entry.where(:user_id => current_user.id, :room_id => params[:message][:room_id]).present?
      @message = Message.create(params.require(:message).permit(:user_id, :content, :room_id).merge(:user_id => current_user.id))
      redirect_to "/rooms/#{@message.room_id}"
    else
      redirect_back(fallback_location: root_path)
    end
  end
end

This section describes the mechanism for creating a message. Make sure that the: message and: room_id keys of all message information including content sent by form_for are properly entered. If the condition is true, set it to Message.create to save the message and allow the values sent as parameters for user_id,: content, room_id in the Messages table. Since the message was sent by the currently logged in user, merge the information for that user_id. And if the condition is false, write flash.now [: alert] to issue a flash message. Finally, with redirect, in both conditions, redirect to the original page and you're done.

Recommended Posts

Rails ~ Understanding the message function ~
[Rails] What was the error message?
[Rails] About the Punk List function
Rails Flash Message
[Rails] Category function
Rails follow function
[Rails] Notification function
About the function double-java
Let's understand the function!
[rails] tag ranking function
Rails search function implementation
Master the [Rails] scope!
Implement application function in Rails
Rails fuzzy search function implementation
[Rails] Implement User search function
Introduced graph function with rails
Search function using [rails] ransack
Implement follow function in Rails
about the where method (rails)
[Rails] I implemented the validation error message by asynchronous communication!
[Rails 6] Implementation of search function
[Rails] Implementation of category function
A note about the seed function of Ruby on Rails
[Rails] (Supplement) Implemented follow function
Login function implementation with rails
[Rails] EC site cart function
Ajax bookmark function using Rails
[Rails] Implementation of tutorial function
[Rails] Implement image posting function
[Rails] Implementation of like function
[Rails] Delete the migration file
[Rails 6] Pagination function implementation (kaminari)
Let's roughly implement the image preview function with Rails + refile + jQuery.
I tried to implement the image preview function with Rails / jQuery
I got a warning message with the rails _6.0.3_ new hello_myapp command
Understanding REST will improve the outlook for Ruby on Rails tutorials
I made a reply function for the Rails Tutorial extension (Part 5):
[Rails] How to put a crown mark on the ranking function
(Ruby on Rails6) Create a function to edit the posted content
[Rails] Implementation of CSV import function
[Rails] Asynchronous implementation of like function
Add a search function in Rails.
[Rails] Check the contents of the object
[Ruby on Rails] Introduced paging function
[Rails] Implementation of image preview function
User evaluation using the like function
[Rails] Tag management function (using acts-as-taggable-on)
About the symbol <%%> in Rails erb
Explanation of the order of rails routes
Implemented mail sending function with rails
Kaminari --Added pagination function of Rails
[Rails] About implementation of like function
[Rails] Implementation of user withdrawal function
[Rails] Implementation of CSV export function
Create pagination function with Rails Kaminari
Implement simple login function in Rails
[Ruby on Rails] CSV output function
[Rails] Voice posting function ~ Cloudinary, CarrierWave
[Rails] Comment function (registration / display / deletion)
[Rails] I tried deleting the application
[Rails] gem ancestry category function implementation