Simple Rails 6 Chat application with Action Cable
Tags: rails, actioncable, webdev, ruby
Published: 2019-11-03 21:06:42

We will create a simple Rails 6 chat application that utilizes web sockets to permit real-time communication. Action Cable meshes websockets with into Rails applications.To begin, we first create a new rails application. 

```
rails new chatter
```

Once the application has been created, we generate a scaffold for our model. As this is a simple implementation of a chat application, our Chat model would only have one field, message

``` 
rails g scaffold Chat  message:string
rails db:migrate
```

Once the scaffold is created, we then set the root path of our application

``` 
chatter/config/routes
 root 'chats#index' 
```

We then update the form for our chat to submit via javascript. Navigate to app/views/chats/_form.html.erb and  update the form to 
```ruby
form_with(model: chat, remote: true)
```
This enables the form to be submitted via javascript. We will also update new.html.erb. We will add a div element that would hold newly created messages through action cable. 
```ruby
<% @chats.each do |chat| %>
<p><%= chat.message %></p>
<% end %>
<div id="new_message"%></div>
```
We will also update the controller to enable the create method to respond to javascript. In chats_controller,update as follows; 
chats_controller, update as follows; 

```ruby 
@chat = Chat.new(chat_params) 
    respond_to do |format| 

      if @chat.save 
        # format.html { redirect_to @chat, notice: 'Chat was successfully created.' } 

        # format.json { render :show, status: :created, location: @chat } 
        format.js
```
Also update the new method to contain the following 
```ruby
def new 

    @chats =Chat.all 

    @chat = Chat.new 

  end
```
Finally, we will also create a create.js.erb file to our views/chats/ folder. 

## Enter Action Cable
As previously stated, Action Cable enables real-time communication via web sockets. To get started, we first generate a channel that we will stream from. Create a new channel 
``` 
rails g channel room
```
This would generate several files. We first look at room_channel.rb. We update the subscribed method to stream from room_channel 
```ruby
 def subscribed
  stream from "room_channel"
 end
```
We then look at room_channel.js. Three functions are defined here. For this application, we are solely interested in the received function. Here, we state what operations should be carried out when channel receives data. We want the new message that was submitted to be displayed on the screen. So we create new elements and pass the message into it and render it out as HTML.
```javascript
  var node = document.createElement("P"); 

    var textnode = document.createTextNode(data.content.message); 

    node.appendChild(textnode); 

    document.getElementById("new_message").appendChild(node);
 document.getElementById('chat_message').value= ''
```
We look at the controller for chats again and update the create method. On the successful creation of a new chat message, we want to broadcast this chat message to our room_channel. We update the create method to reflect these changes: 
```ruby 
def create 

    @chat = Chat.new(chat_params) 
    respond_to do |format| 
      if @chat.save 
        ActionCable.server.broadcast 'room_channel', content: @chat 
        format.html { redirect_to @chat, notice: 'Chat was successfully created.' } 
        format.json { render :show, status: :created, location: @chat } 
        format.js 
      else 
        format.html { render :new } 
        format.json { render json: @chat.errors, status: :unprocessable_entity } 
      end 
    end 
  end 
```
We can finally test our application to see our chat work in real-time! That’s it! 

 ![GIF of Chat app](https://media.giphy.com/media/emGcqfIrph4jInfuz1/giphy.gif)
{% github timnans/chatter %}