Ruby on Rails 자습서 DM 기능 추가
16024 단어 Rails 튜토리얼루비Rails
소개
Ruby on Rals 튜토리얼 (5.1 버전) 과제의 "DM 기능"을 작성합니다.
튜토리얼의 계속으로부터 기능을 추가하고 있기 (위해)때문에 User 모델·헬퍼 메소드의 작성등은 실시하고 있지 않으시기 때문에 주의해 주세요.
또한 Action Cable을 사용하지 않고 메시지를 보낼 때마다 모든 메시지를 검색한다는 처리를 실시하고 있습니다.
또한이 기사에서는
Ruby 2.7.2
Rails 5.1
사용하고 있습니다.
만드는 것
users/:id/messages에 DM을 표시하고 메시지 전송 기능도 갖게 합니다.
message 모델 작성, User 모델과의 연관
$ rails g model Message from_id:integer to_id:integer content:text
발신자의 id, 수신자의 id로 메시지를 판별하고 있습니다.
db/migrate/유일한 숫자_create_messages.rbclass CreateMessages < ActiveRecord::Migration[5.1]
def change
create_table :messages do |t|
t.integer :from_id
t.integer :to_id
t.text :content
t.timestamps
end
add_index :messages, :from_id
add_index :messages, :to_id
end
end
from_id,to_id에 index를 붙여 migration을 실시합니다.$ rails db:migrate
app/models/message.rbclass Message < ApplicationRecord
default_scope -> { order(created_at: :asc) }
validates :from_id, presence: true
validates :to_id, presence: true
validates :content, presence: true, length: { maximum: 300 }
end
메시지 순서, 유효성 검사를 설정합니다.
app/models/user.rbclass User < ApplicationRecord
has_many :outgoing_messages, class_name: "Message",
foreign_key: "from_id",
dependent: :destroy
has_many :incoming_messages, class_name: "Message",
foreign_key: "to_id",
dependent: :destroy
.
.
.
end
User 모델과의 부착을 실시합니다.
라우팅
config/routes.rbRails.application.routes.draw do
resources :users do
member do
resources :messages, only: [:create, :index]
end
end
end
다음 라우팅 완료
GET /users/:id/messages(.:format) messages#index
POST /users/:id/messages(.:format) messages#create
index 액션으로 특정 상대와의 메세지 일람을 렌더링 해, create 액션으로 신규 메세지를 송신+view의 갱신을 실시합니다.
Messages 컨트롤러 처리
$ rails g controller Messages index create
Messages 컨트롤러를 작성합니다.
app/controllers/messages_controller.rbclass MessagesController < ApplicationController
before_action :setup_users
def index
@messages = Message.where("from_id IN (:ids) AND to_id IN (:ids)",ids:@ids)
@message = Message.new
end
def create
@message = current_user.outgoing_messages.build(message_params)
@message.to_id = params[:id]
@message.save
@messages = Message.where("from_id IN (:ids) AND to_id IN (:ids)",ids:@ids)
respond_to do |format|
format.html { redirect_to messages_urL(@to_user)}
format.js { render "create"}
end
end
private
def message_params
params.require(:message).permit(:content)
end
def setup_users
@to_user = User.find(params[:id])
@ids = [@to_user.id,current_user.id]
end
end
index 메소드에서
from 또는 to 컬럼에 자신 또는 상대의 id 를 포함한 message 를 꺼내 인스턴스 변수에 보존하고 있습니다.
create 메소드로 처리
이번에는 Action Cable을 사용하지 않기 때문에 상대방이 송신한 신규 메시지를 취득하기 위해 메시지 송신 실패·성공에 관계없이 메시지를 모두 취득합니다.
또한 current_user 메소드는 rails tutorial에서 작성한 것입니다.
보기
우선은 index 메소드로부터 렌더링 되는 index.html.erb 입니다.
app/views/messages/index.html.erb<h2><%= @to_user.name %></h2>
<ol id="messages">
<%= render @messages %>
</ol>
<div id="error_messages">
<%= render "shared/error_messages", object:@message %>
</div>
<%= render "shared/message_form" %>
app/views/messages/_message.html.erb<li <%= "class = my-content" if message.from_id == current_user.id %>>
<%= gravatar_for message.from, size: 50 %>
<div class="content">
<span class="message">
<%= message.content %>
</span>
<span class="timestamp">
<%= message.created_at %>
</span>
</div>
</li>
Twitter 등에서 볼 수 있듯이 상대의 메시지와 자신의 메시지의 표시 방법을 바꾸기 위해, 자신의 메시지의 경우는 다른 css를 적용하기 위한 클래스명을 붙이는 처리를 하고 있습니다.
app/views/shared/_message_form.html.erb<% provide(:button_text, 'Send Message') %>
<%= form_with model: @message do |f| %>
<%= f.text_area :content, class: 'form-control' %>
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>
app/views/shared/_error_messages.html.erb<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
다음에 create 메소드로 렌더링 되는 view입니다.
app/views/messages/create.js.erb$(".form-control").val("");
$("#messages").html("<%= escape_javascript(render(@messages)) %>");
$("#error_messages").html("<%= escape_javascript(render('shared/error_messages', object: @message)) %>");
양식을 지우고, 메시지를 가져오고, 오류 메시지를 표시합니다.
scss
app/assets/stylesheets/custom.scss// messages
#messages {
list-style: none;
padding: 0;
li {
padding: 10px 0;
// border-top: 1px solid #e8e8e8;
display: flex;
justify-content: flex-start;
}
.content {
display: inline-block;
.message {
padding: 20px;
display: inline-block;
background:$gray-medium-light;
border-radius: 10px;
}
.timestamp {
color: $gray-light;
display: block;
font-size: .75em;
}
}
.gravatar {
margin-right: 10px;
width: 40px;
height: 40px;
}
li.my-content{
justify-content: flex-end;
text-align: right;
.message {
background:#71151a;
border-radius: 10px;
color: #fff;
}
.gravatar{
display: none;
}
}
}
완성
현재 자신이 메시지를 보낼 때만 새로운 메시지를 얻을 수 있기 때문에 Action Cable을 이용하여 실시간 채팅 기능 추가 등을 실시하고 싶습니다.
Reference
이 문제에 관하여(Ruby on Rails 자습서 DM 기능 추가), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/akmhmgc/items/3dc55bd52391ef7b0580
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class CreateMessages < ActiveRecord::Migration[5.1]
def change
create_table :messages do |t|
t.integer :from_id
t.integer :to_id
t.text :content
t.timestamps
end
add_index :messages, :from_id
add_index :messages, :to_id
end
end
class Message < ApplicationRecord
default_scope -> { order(created_at: :asc) }
validates :from_id, presence: true
validates :to_id, presence: true
validates :content, presence: true, length: { maximum: 300 }
end
class User < ApplicationRecord
has_many :outgoing_messages, class_name: "Message",
foreign_key: "from_id",
dependent: :destroy
has_many :incoming_messages, class_name: "Message",
foreign_key: "to_id",
dependent: :destroy
.
.
.
end
Rails.application.routes.draw do
resources :users do
member do
resources :messages, only: [:create, :index]
end
end
end
GET /users/:id/messages(.:format) messages#index
POST /users/:id/messages(.:format) messages#create
class MessagesController < ApplicationController
before_action :setup_users
def index
@messages = Message.where("from_id IN (:ids) AND to_id IN (:ids)",ids:@ids)
@message = Message.new
end
def create
@message = current_user.outgoing_messages.build(message_params)
@message.to_id = params[:id]
@message.save
@messages = Message.where("from_id IN (:ids) AND to_id IN (:ids)",ids:@ids)
respond_to do |format|
format.html { redirect_to messages_urL(@to_user)}
format.js { render "create"}
end
end
private
def message_params
params.require(:message).permit(:content)
end
def setup_users
@to_user = User.find(params[:id])
@ids = [@to_user.id,current_user.id]
end
end
<h2><%= @to_user.name %></h2>
<ol id="messages">
<%= render @messages %>
</ol>
<div id="error_messages">
<%= render "shared/error_messages", object:@message %>
</div>
<%= render "shared/message_form" %>
<li <%= "class = my-content" if message.from_id == current_user.id %>>
<%= gravatar_for message.from, size: 50 %>
<div class="content">
<span class="message">
<%= message.content %>
</span>
<span class="timestamp">
<%= message.created_at %>
</span>
</div>
</li>
<% provide(:button_text, 'Send Message') %>
<%= form_with model: @message do |f| %>
<%= f.text_area :content, class: 'form-control' %>
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
$(".form-control").val("");
$("#messages").html("<%= escape_javascript(render(@messages)) %>");
$("#error_messages").html("<%= escape_javascript(render('shared/error_messages', object: @message)) %>");
// messages
#messages {
list-style: none;
padding: 0;
li {
padding: 10px 0;
// border-top: 1px solid #e8e8e8;
display: flex;
justify-content: flex-start;
}
.content {
display: inline-block;
.message {
padding: 20px;
display: inline-block;
background:$gray-medium-light;
border-radius: 10px;
}
.timestamp {
color: $gray-light;
display: block;
font-size: .75em;
}
}
.gravatar {
margin-right: 10px;
width: 40px;
height: 40px;
}
li.my-content{
justify-content: flex-end;
text-align: right;
.message {
background:#71151a;
border-radius: 10px;
color: #fff;
}
.gravatar{
display: none;
}
}
}
Reference
이 문제에 관하여(Ruby on Rails 자습서 DM 기능 추가), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/akmhmgc/items/3dc55bd52391ef7b0580텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)