[Rails應用實戰]WebChat的敏捷開發

即時通訊的應用如微信WeChat大家一定很熟悉,那麼今天就來詳解一下如何用Rails快速開發一款網頁版微信(網頁版聊天室)

所有代碼在Github中,目前已有功能:

  • 即時通訊
  • 增添好友
  • 創建聊天
  • 拉人,刪人
  • 轉移房屋權限

Todo

  1. UI界面修改(類似WeChat)
  2. 未讀信息的提醒(包括聲音)
  3. 加入更多的ajax提高用戶體驗

代碼實現

我們主要應用了Render_sync庫來提供服務器監聽並實時推送信息的功能,下面的實現貼出一些主要的部分,詳細的請到Github中下載代碼查看:

  1. 首先加入render_sync等庫,編輯Gemfile文件,加入以下

    gem 'faye'
    gem 'thin', require: false
    gem 'render_sync'
  2. 創建User,Message,Chat,FriendShip四個模型,之間的關係分別爲:

    class Chat < ActiveRecord::Base
      has_and_belongs_to_many :users
      has_many :messages, :dependent => :destroy
    end
    class Friendship < ActiveRecord::Base
      belongs_to :user
      belongs_to :friend, :class_name => "User"
    end
    class Message < ActiveRecord::Base
      belongs_to :user
      belongs_to :chat
    
      sync :all
      sync_scope :by_chat, ->(chat) { where(chat_id: chat.id) }
    end
    class User < ActiveRecord::Base
    
      has_many :messages
      has_and_belongs_to_many :chats
    
      has_many :friendships
      has_many :friends, :through => :friendships
      has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id"
      has_many :inverse_friends, :through => :inverse_friendships, :source => :user
    
      .....
    
    end
  3. 編寫各個模型的migrate文件,這裏不貼出來,詳細請看這裏,創建seed.rb文件,寫入初始數據:

    (1..100).each do |index|
      User.create(
          name: Faker::Name.name,
          email: "user#{index}@test.com",
          password: 'password',
          role: Faker::Number.between(1, 4),
          sex: ['male', 'female'].sample,
          phonenumber: Faker::PhoneNumber.phone_number,
          status: Faker::Company.profession
      )
    end
    
    User.first.friendships.create(:friend_id => 2)
    User.first.friendships.create(:friend_id => 3)
  4. 編寫ChatsController,FriendshipsController, MessagesController, SessionsController以及UsersController,如這裏所示,以及各個控制器下的試圖,如這裏所示

  5. 這裏主要講解Render_sync庫的用法,在ChatsController的show方法的視圖中,這兩句起到了推送實時信息的功能:

                    <%= sync partial: 'message_row', collection: Message.by_chat(@chat), refetch: true %>
                    <%= sync_new partial: 'message_row', resource: Message.new, scope: @chat, refetch: true %>
    • refetch: true選項能決定推送的方式爲ajax
    • scope: @chat 能決定推送消息的範圍,例如只給當前聊天室頁面的client實時推送新的消息
    • collection: Message.by_chat(@chat) 能決定歷史信息爲當前聊天室的信息,而不是所有的所有的信息都在當前聊天室顯示

    局部視圖文件需要位於app/views/sync/messages/refetch/_message_row.html.erb才能生效,這個局部視圖負責就是每條消息的顯示,例如消息的主題,發送人和發送時間,簡化後爲:

    <p>
    <%= message.user.name %>
    <%= message.created_at.to_formatted_s(:db) %>
    <%= message.body %>
    </p>
  6. 最重要的爲MessagesController的create方法,這個方法接受兩個參數,一個是發送的message,一個是聊天室的id,創建發送的message後,將此message與當前聊天室關聯,然後調用sync_new方法同步推送此message,推送的範圍爲此聊天室,最後重定向至此聊天室

    class MessagesController < ApplicationController
      ...
    
      def create
        @message = current_user.messages.build(message_params)
        chat=Chat.find_by_id(params[:chat_room])
        @message.chat=chat
        if @message.save
          sync_new @message, scope: chat
        end
        redirect_to chat_path(chat)
      end
    
      ....
    
    end
  7. 最後編輯聊天室中的發送框即可,在ChatsController的show方法視圖下,加入:

    <%= form_for @new_message, remote: true do |f| %>
        <div class="input-group">
          <%= f.text_field :body, class: "form-control input-sm", placeholder: "Type your message here..." %>
          <span class="input-group-btn"> <%= f.submit "發送", class: "btn btn-warning btn-sm" %> </span>
          <%= hidden_field_tag :chat_room, @chat.id %>
        </div>
    <% end %>
    • 使用hidden_field_tag傳入此聊天室的id
    • remote: true 使表單用ajax方法提交
  8. 完成其他模塊,運行服務器

結果截屏

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

如何使用

  1. Fork項目,https://github.com/PENGZhaoqing/RailsChat

    git clone https://github.com/your_user_name/RailsChat
    cd RailsChat
    bundle install
    rails server
  2. 然後再打開另外一個終端,運行以下命令啓動另外一個server來監聽聊天室的用戶並實時推送最新的消息:

    rackup sync.ru -E production

Note:如果要部署到雲上或者本地局域網內,需要修改config/sync.yml文件

以本地局域網爲例:

  1. 若本機的ip地址爲192.168.0.14(使用ifconfig查看),那麼需要將config/sync.yml中的localhost全改爲此ip地址,例如

    development:
    server: "http://192.168.0.14:9292/faye"
    adapter_javascript_url: "http://192.168.0.14:9292/faye/faye.js"
    auth_token:  "97c42058e1466902d5adfac0f83e84c1794b9c3390e3b0824be9db8344eae82b"
    adapter: "Faye"
    async: true
    
    test:
    ...
    production:
    ...
  2. 然後運行rake tmp:clear來清除緩存,不然修改不會生效(運行前先將所有相關的運行停止:如rails s,rackup sync.ru等)

  3. 再次運行rails服務器和監聽程序,並指定監聽程序運行的ip地址

    rails s
    rackup sync.ru -E production --host 192.168.0.14 

Debug

  1. 當遇到消息並沒有實時推送的情況時,先F12查看瀏覽器的Js文件加載情況,若faye.js加載成功則一般不會出現問題

  2. 以上加載完成但是仍然沒有推送的時候,請查看Rails服務器的log文件

  3. 需要在兩個瀏覽器中登錄不同的賬號來檢驗聊天室功能

發佈了46 篇原創文章 · 獲贊 132 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章