戻る

Rails6.0


動画学習サイトの構築 Rails6.0

  (0)
2,000円

タスク7-6   通知

このタスクについて


タスクの内容を一部抜粋します。
プロジェクトを購入していただくとこのタスクの内容の全てを読みやすい表示で見ることができます。
プログラムコードが色分けされて見やすくなります。
プログラムコードに行番号が付きます。
本文が色分けされて見やすくなります。
そしてこのアプリケーションのフルコードをダウンロードすることが可能になります。




コマンド
rails g model Notification content user:references


コマンド
rails g migration AddUnreadToUser unread:bigint


記述追加 db\migrate\20200805024555_add_unread_to_user.rb
3行目末尾に「, default: true」の記述追加
 
class AddUnreadToUser < ActiveRecord::Migration[6.0] 
  def change 
    add_column :users, :unread, :bigint, default: true 
  end 
end 



コマンド マイグレーション
rails db:migrate


記述追加 app\models\user.rb
7行目に「has_many :notifications」の記述追加
 
class User < ApplicationRecord 

  has_many :projects 
  has_many :subscriptions 
  has_many :projects, through: :subscriptions 
  has_many :reviews 
  has_many :notifications 

  has_one_attached :avatar 

  # Include default devise modules. Others available are: 
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable 
  devise :database_authenticatable, :registerable, 
         :recoverable, :rememberable, :validatable, 
         :confirmable, :omniauthable 

  #長さ50文字以下 入力必須 
  validates :full_name, presence: true, length: {maximum: 50} 

  def self.from_omniauth(auth) 
    user = User.where(email: auth.info.email).first 
    if user 
      if !user.provider 
        user.update(uid: auth.uid, provider: auth.provider, image: auth.info.image) 
      end    
      return user 
    else 
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user| 
        user.email = auth.info.email 
        user.password = Devise.friendly_token[0, 20] 
        user.full_name = auth.info.name   # ユーザーモデルに名前があると仮定 
        user.image = auth.info.image # ユーザーモデルに画像があると仮定 
        user.uid = auth.uid 
        user.provider = auth.provider 
      end 
    end 
  end  
end 



記述追加 app\models\notification.rb
2行目に「after_create_commit { NotificationJob.perform_later self }」の記述追加
 
class Notification < ApplicationRecord 
  after_create_commit { NotificationJob.perform_later self } 
  belongs_to :user 
end 



「app\models\message.rb」ファイルを以下のように編集します。


1.5行目に以下の記述を追加します。
after_create_commit :create_notification



2.9行目に以下の記述を追加します。
 
  private 
  def create_notification 
    if self.conversation.sender_id == self.user_id 
      sender = User.find(self.conversation.sender_id) 
      Notification.create(content: "#{sender.full_name}から新しいメッセージがあります。", user_id: self.conversation.receiver_id) 
    else 
      sender = User.find(self.conversation.receiver_id) 
      Notification.create(content: "#{sender.full_name}から新しいメッセージがあります。", user_id: self.conversation.sender_id) 
    end 
  end  



app\models\message.rb
 
class Message < ApplicationRecord 

  belongs_to :user 
  belongs_to :conversation 

  after_create_commit :create_notification 

  validates :content, presence: { message: '空白にはできません' } 

  private 
  def create_notification 
    if self.conversation.sender_id == self.user_id 
      sender = User.find(self.conversation.sender_id) 
      Notification.create(content: "#{sender.full_name}から新しいメッセージがあります。", user_id: self.conversation.receiver_id) 
    else 
      sender = User.find(self.conversation.receiver_id) 
      Notification.create(content: "#{sender.full_name}から新しいメッセージがあります。", user_id: self.conversation.sender_id) 
    end 
  end  
end 



「app\controllers」フォルダに「notifications_controller.rb」ファイルを新規作成して下さい。


app\controllers\notifications_controller.rb(新規作成したファイル)
 
class NotificationsController < ApplicationController 

    before_action :authenticate_user! 
  
    def index 
      current_user.unread = 0 
      current_user.save 
      @notifications = current_user.notifications.order(created_at: "DESC") 
    end 
end 



コマンド
rails g channel notifications


「app\javascript\channels」フォルダに「notifications.coffee」ファイルを新規作成してください。


app\javascript\channels\notifications.coffee(新規作成したファイル)
 
$(() -> 
  App.notifications = App.cable.subscriptions.create {channel: "NotificationsChannel", id: $('#user_id').val() }, 
    received: (data) -> 
      $('#num_of_unread').html(data.unread) 
      $('#notifications').prepend(data.message) 
      $('#navbar_num_of_unread').html(data.unread) 
) 



書き換え app\channels\notifications_channel.rb
 
class NotificationsChannel < ApplicationCable::Channel 
  def subscribed 
    stream_from "notification_#{params[:id]}" 
  end 
end 



コマンド
rails g job notification


書き換え app\jobs\notification_job.rb
 
class NotificationJob < ApplicationJob 

  queue_as :default 

  def perform(notification) 
    notification.user.increment!(:unread) 
    ActionCable.server.broadcast "notification_#{notification.user.id}", message: render_notification(notification), unread: notification.user.unread 
  end 

  private 
    def render_notification(notification) 
      ApplicationController.render(partial: 'notifications/notification', locals: { notification: notification}) 
    end 
end 



記述追加 config\routes.rb
20行目に「get '/notifications' => 'notifications#index'」の記述追加
 
Rails.application.routes.draw do 

  # ルートを app\views\pages\home.html.erb に設定 
  root 'pages#home' 

  mount ActionCable.server => '/cable' 

  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, 
              controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'} 

  get 'pages/home' 
  get '/dashboard', to: 'users#dashboard' 
  get '/users/:id', to: 'users#show', as: 'users' 
  get '/myprojects' => 'project#list' 
  get 'settings/payment', to: 'users#payment', as: 'settings_payment' 
  get '/conversations', to: 'conversations#list', as: "conversations" 
  get '/conversations/:id', to: 'conversations#show', as: "conversation_detail" 
  get '/notifications' => 'notifications#index' 

  post '/users/edit', to: 'users#update' 
  post '/free' => 'charge#free' 
  post '/settings/payment', to: 'users#update_payment', as: "update_payment" 
  post '/reviews', to: 'reviews#create' 
  post 'messages', to: 'messages#create' 

  resources :project do 
    resources :task, only: [:show] 
    resources :reviews, only: [:create, :destroy] 
  end  

  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html 
end 



「app\views」フォルダに「notifications」フォルダを新規作成してください。
作成した「notifications」フォルダに「index.html.erb」ファイルを新規作成します。



app\views\notifications\index.html.erb(新規作成したファイル)
 
<section class="section"> 
    <div class="container"> 
        <div style="margin-left: 50px; margin-bottom: 30px;"> 
            <%= link_to 'メッセージを見る', conversations_path, class: "button is-primary" %> 
        </div> 
        <table class="table" style="margin-left: 50px; margin-bottom: 50px;"> 
            <div class="container" id="notifications"> 
                <% @notifications.each do |n| %> 
                    <tr> 
                        <td> 
                            <strong><%= n.content %></strong> 
                            <span class="pull-right"><%= time_ago_in_words(n.created_at) %>&nbsp;&nbsp;&nbsp;(&nbsp;<%= n.created_at.strftime('%Y年%-m月%-d日 %-H時%-M分') %>&nbsp;)&nbsp;</span> 
                        </td> 
                    </tr> 
                <% end %> 
            </div> 
        </table> 
    </div> 
</section> 



ダッシュボードビューを更新します。


記述追加 app\views\users\dashboard.html.erb(11行目)
 
<!--通知 --> 
<article class="media"> 
    <div class="content" style="margin-left: 30px; margin-bottom: 10px;"> 
        <%= link_to notifications_path do %> 
            <span id="num_of_unread"><%= current_user.unread %></span> 件の通知があります。 
        <% end %> 
    </div> 
</article> 



app\views\users\dashboard.html.erb
 
<section class="section"> 
    <div class="container"> 
        <div class="columns"> 
        
            <!-- 左パネル --> 
            <div class="column is-one-third"> 
                <div class="columns is-multiline"> 
                    <!-- 上部 --> 
                    <div class="column is-full"> 
                        <!--通知 --> 
                        <article class="media"> 
                            <div class="content" style="margin-left: 30px; margin-bottom: 10px;"> 
                                <%= link_to notifications_path do %> 
                                    <span id="num_of_unread"><%= current_user.unread %></span> 件の通知があります。 
                                <% end %> 
                            </div> 
                        </article> 
                        <div class="card"> 
                            <!-- アバター --> 
                            <div class="card-content is-horizontal-center is-flex"> 
                                <figure class="image is-256x256"> 
                                    <%= image_tag avatar_url(current_user), class: "is-rounded" %> 
                                </figure> 
                            </div> 
                            
                            <div class="card-content"> 
                                <!-- 画像アップロードボタン --> 
                                <div class="content has-text-centered"> 
                                    <p class="title is-5"> 
                                        <%= current_user.full_name %> 
                                    </p> 
                                <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post do |f| %> 
                                    <div class="file"> 
                                        <label class="button is-primary is-outlined is-fullwidth"> 
                                            <%= f.file_field :avatar, class: "file-input", onchange: "this.form.submit();" %> 
                                            <i class="fas fa-upload"></i>&nbsp;&nbsp;&nbsp; アバター画像アップロード 
                                        </label> 
                                    </div> 
                                <% end %>   
                                </div> 
                                <hr class="h-10"> 
                                
                                <!-- アカウント情報 --> 
                                <article class="media"> 
                                    <div class="media-content">アカウント登録日</div> 
                                    <div class="media-right"> 
                                        <strong><%= I18n.l(current_user.created_at, format: :full_date) %></strong> 
                                    </div> 
                                </article> 
                                <hr class="h-10"> 
                                
                                <!-- オンラインステータス --> 
                                <article> 
                                    <div class="media"> 
                                        <div class="media-content">ステータス</div> 
                                        <div class="media-right"> 
                                            <strong><% if current_user.status %> オンライン <% else %> オフライン <% end %></strong> <i class="toggle far fa-edit" aria-controls="user-status"></i> 
                                        </div> 
                                    </div> 
                                    <div class="content"> 
                                        <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post, html: {id: 'user-status', class: 'is-hidden'} do |f| %> 
                                            <div class="field"> 
                                                <%= f.select(:status, options_for_select([["オンライン", true], ["オフライン", false]]), {}, {class: "select is-fullwidth"}) %> 
                                            </div> 
                                            <a class="toggle button is-light" aria-controls="user-status">キャンセル</a> 
                                            <%= f.submit "保存", class: "button is-danger" %> 
                                        <% end %> 
                                    </div> 
                                </article> 
                            </div> 
                        </div> 
                    </div> 
                    <!-- 下部 --> 
                    <div class="column is-full"> 
                        <div class="card"> 
                            <div class="card-content"> 
                                <!-- アカウント詳細 --> 
                                <article> 
                                    <div class="media"> 
                                        <div class="media-content"> 
                                            <p> 
                                                <strong>自己紹介</strong> 
                                                <br> 
                                                <%= current_user.about %> 
                                            </p> 
                                        </div> 
                                        <div class="media-right"> 
                                            <i class="toggle far fa-edit" aria-controls="user-about"></i> 
                                        </div> 
                                    </div> 
                                    <div class="content"> 
                                        <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post, html: {id: 'user-about', class: 'is-hidden'} do |f| %> 
                                            <div class="field"> 
                                                <%= f.text_area :about, autofocus: true, autocomplete: 'form', class: 'input'%> 
                                            </div> 
                                            <a class="toggle button is-light" aria-controls="user-about">キャンセル</a> 
                                            <%= f.submit "保存", class: "button is-danger" %> 
                                        <% end %> 
                                    </div> 
                                </article> 
                                <hr class="h-10"> 
                                
                                <!-- アカウント連携 --> 
                                <article class="media"> 
                                    <div class="content"> 
                                        <p> 
                                            <strong>アカウント連携</strong><br/> 
                                            <% if current_user.provider == 'google_oauth2' %> 
                                                <span class="has-text-success">Googleアカウントでログイン中</span> 
                                            <% else %> 
                                                <span class="has-text-danger">アカウント連携していません</span> 
                                            <% end %> 
                                        </p> 
                                    </div> 
                                </article> 
                            </div> 
                        </div> 
                    </div> 
                </div> 
            </div> 
            <!-- 右側 --> 
            <div class="column"> 
                <div class="columns is-multiline"> 
                    <!-- 購入したプロジェクト --> 
                    <div class="column is-one-third has-text-centered"> 
                    
                    </div> 
                </div> 
            </div> 
            
        </div> 
    </div> 
</section> 





この続きはプロジェクトを購入していただくことで見ることができます。
プロジェクトを購入していただくとこのタスクの内容の全てを読みやすい表示で見ることができます。
プログラムコードが色分けされて見やすくなります。
プログラムコードに行番号が付きます。
本文が色分けされて見やすくなります。
そしてプロジェクトを購入するとこのアプリケーションのフルコードをダウンロードすることができます。

まだレビューはありません。

動画学習サイトの構築 Rails6.0

2,000円

Rails6.0で作成しています。
動画で学べるサイトを構築するプロジェクトです。
プロジェクトを登録し、そのプロジェクトに動画を登録できます。
プロジェクトはクレジットカードで購入でき、購入後すぐに動画を見ることができます。
写真の複数アップロード、レビュー機能の実装、Google認証、アマゾンS3の利用方法も解説。
管理ダッシュボードtrestleの実装、Gメールの設定、 HEROKUへのデプロイ方法を解説。
質問があればメッセージを送ることができ、リアルタイムで会話表示することができます。
フルコードのダウンロード可能。

タスク数: 128