学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

【民泊5.1】【MacOSX】アクションケーブル

アクションケーブルを使ってリアルタイムでメッセージが更新されるようにします。


記述追加 config\routes.rb
6行目に「mount ActionCable.server => '/cable'」の記述追加

Rails.application.routes.draw do

  #ルートをpages#homeに設定
  root 'pages#home'

  # アクションケーブル
  mount ActionCable.server => '/cable'

  get 'pages/home'
  get '/your_trips' => 'reservations#your_trips'
  get '/your_reservations' => 'reservations#your_reservations'
  get 'search' => 'pages#search'
  get 'dashboard' => 'dashboards#index'
  get '/host_calendar' => "calendars#host"
  get '/payment_method' => "users#payment"
  get '/payout_method' => "users#payout"
  get '/notification_settings' => 'settings#edit'

  post '/add_card' => "users#add_card"
  post '/notification_settings' => 'settings#update'

  resources :users, only: [:show] do
    member do
      post '/verify_phone_number' => 'users#verify_phone_number'
      patch '/update_phone_number' => 'users#update_phone_number'
    end
  end

  resources :rooms, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
      get 'preload'
      get 'preview'
    end
    resources :photos, only: [:create, :destroy]
    resources :reservations, only: [:create]
    resources :calendars
  end

  resources :guest_reviews, only: [:create, :destroy]
  resources :host_reviews, only: [:create, :destroy]

  resources :revenues, only: [:index]

  resources :reservations, only: [:approve, :decline] do
    member do
      post '/approve' => "reservations#approve"
      post '/decline' => "reservations#decline"
    end
  end

  resources :conversations, only: [:index, :create]  do
    resources :messages, only: [:index, :create]
  end

  devise_for :users,
  path: '',
  path_names: {sign_in: 'login', sign_out: 'logout', edit: 'profile', sign_up: 'registration'},
  controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'}
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end



記述更新 app\assets\javascripts\application.js
25行目に「//= require cable」の記述追加

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require bootstrap-sprockets
//= require jquery_ujs
//= require jquery-ui/datepicker
//= require jquery-ui/slider
//= require toastr
//= require moment
//= require fullcalendar
//= require gravtastic
//= require card
//= require Chart.bundle
//= require chartkick
//= require cable
//= require turbolinks
//= require_tree .



記述追加 config\environments\development.rb
59行目に「config.action_cable.url = "ws://localhost:3000/cable"」の記述追加

Rails.application.configure do

  #画像アップロード
  Paperclip.options[:command_path] = "/usr/local/bin/"

  # Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports.
  config.consider_all_requests_local = true

  # Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist?
    config.action_controller.perform_caching = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => 'public, max-age=172800'
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = true

  config.action_mailer.perform_caching = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise an error on page load if there are pending migrations.
  config.active_record.migration_error = :page_load

  # Debug mode disables concatenation and preprocessing of assets.
  # This option may cause significant delays in view rendering with a large
  # number of complex assets.
  config.assets.debug = true

  # Suppress logger output for asset requests.
  config.assets.quiet = true

  # Raises error for missing translations
  # config.action_view.raise_on_missing_translations = true

  # Use an evented file watcher to asynchronously detect changes in source code,
  # routes, locales, etc. This feature depends on the listen gem.
  config.file_watcher = ActiveSupport::EventedFileUpdateChecker

  #アクションケーブル
  config.action_cable.url = "ws://localhost:3000/cable"

  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

   #Gメールの設定
   config.action_mailer.delivery_method = :smtp

   config.action_mailer.smtp_settings = {
     address: "smtp.gmail.com",
     port: 587,
     enable_starttls_auto: true,
     authentication: "plain",
     user_name: 'win.rails.learn@gmail.com',
     password: 'vusopllqzbyvvahk'
   }
  
   # アマゾンS3
   config.paperclip_defaults = {
    storage: :s3,
    path: ':class/:attachment/:id/:style/:filename',
    s3_host_name: 's3-ap-northeast-1.amazonaws.com',
    s3_credentials: {
      bucket: 'winrailslearn',
      access_key_id: 'AKIAIU4EZ4WK4HU35G4Q',
      secret_access_key: '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',
      s3_region: 'ap-northeast-1'
      }
    }

end



記述追加 app\views\layouts\application.html.erb
7行目に「<%= action_cable_meta_tag %>」の記述追加

<!DOCTYPE html>
<html>
  <head>
    <title>Minpaku</title>
    <%= csrf_meta_tags %>

    <!-- アクションケーブル -->
    <%= action_cable_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <!-- googleフォント -->
    <link href="https://fonts.googleapis.com/css2?family=Kosugi&display=swap" rel="stylesheet">
    <!-- アイコン -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <!-- 日付ピッカー デザインsunny-->
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/sunny/jquery-ui.css">
    <!-- 日付ピッカーの日本語化-->
    <script src="https://rawgit.com/jquery/jquery-ui/master/ui/i18n/datepicker-ja.js"></script>
    <!-- geocomplete -->
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBojDcZmScBkIOISjoYREjgid99iZUL2Tk&libraries=places"></script>
  </head>

  <body>

    <!-- _navbar.html.erb をレンダーする -->
    <%= render 'shared/navbar' %>
    <%= render 'shared/message' %>

    <!-- ページをコンテナに格納 -->
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>



コマンド
rails g channel messages


書き換え app\channels\messages_channel.rb

class MessagesChannel < ApplicationCable::Channel
  def subscribed
    stream_from "conversation_#{params[:id]}"
  end
end



「app\controllers\messages_controller.rb」ファイルを編集します。


1.記述追加 app\controllers\messages_controller.rb(20行目)

ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)



2.21行目の記述をコメントアウトします。

#redirect_to conversation_messages_path(@conversation)



3.記述追加 app\controllers\messages_controller.rb(27行目)

    def render_message(message)
      self.render(partial: 'messages/message', locals: {message: message})
    end



app\controllers\messages_controller.rb

class MessagesController < ApplicationController
    
    before_action :authenticate_user!
    before_action :set_conversation
  
    def index
      if current_user == @conversation.sender || current_user == @conversation.recipient
        @other = current_user == @conversation.sender ? @conversation.recipient : @conversation.sender
        @messages = @conversation.messages.order("created_at DESC")
      else
        redirect_to conversations_path, alert: "権限がありません。"
      end
    end
  
    def create
      @message = @conversation.messages.new(message_params)
      @messages = @conversation.messages.order("created_at DESC")
  
      if @message.save
        ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
        # redirect_to conversation_messages_path(@conversation)
      end
    end
  
    private

    def render_message(message)
      self.render(partial: 'messages/message', locals: {message: message})
    end    

    def set_conversation
        @conversation = Conversation.find(params[:conversation_id])
    end

    def message_params
        params.require(:message).permit(:context, :user_id)
    end

end



書き換え app\assets\javascripts\channels\messages.coffee

$(() ->
  App.messages = App.cable.subscriptions.create {channel: 'MessagesChannel', id: $('#conversation_id').val() },
    received: (data) ->
      $('#new_message')[0].reset()
      $('#chat').prepend data.message
)



ブラウザ確認
http://localhost:3000/conversations/1/messages


メッセージを送信したと同時に更新され、相手の画面にもメッセージが表示されます。

リアルタイムメッセージ
リアルタイムメッセージ