Skip to content

wojnar48/lax

Repository files navigation

README

Slack-inspired, single-page chat app with a RESTful Ruby on Rails API and PostgreSQL backend that serves JSON data to a React / Redux front-end.

lax image

Lax Live

Technologies & Gems

  • Ruby on Rails - back-end API
  • PostgreSQL - database
  • React - front-end rendering
  • Redux - front-end state management
  • jQuery - AJAX requests and DOM manipulation
  • Pusher - real-time chat and notifications
  • AWS S3 - cloud storage for user avatars
  • jbuilder gem - data curation on back-end
  • figaro gem - secure handling of API keys
  • paperclip gem - used with ActiveRecord to allow models to store files easily
  • bcrypt gem - used for custom authentication logic

Features & Implementation

Authentication

Lax has custom authentication logic developed from scratch using the BCrypt gem and hashing algorithm. User passwords are digested and stored in the database as hashes that are used by the SessionsController to manage login/logout logic. On successful login, each user is assigned a url-safe session token generated by the SecureRandom gem which is then stored in the current user's cookies to allow for current session management.

Real-Time Features

Live chat features are implemented using the Pusher API which allows for real-time, bidirectional communication via WebSockets. User actions on the front-end fire AJAX requests that in turn trigger events on the back-end that are braodcast to all subscribers who are bound to those events. This gives users the ability to experience updates without the need to refresh the page. The snippet below subscribes and binds the client to the new-message event as soon as the component is mounted, while the conditional statement ensures that only the current active channel sees the new message.

componentDidMount () {
  const messages = this.pusher.subscribe('messages');
  messages.bind('new-message', (data) => {
    const message = data.message;
    if (message.chatroomId === this.props.activeChannel.id) {
      this.props.receiveMessage(message);
    } else {
      const notification = {
        dmId: message.chatroomId,
        authorId: message.userId,
        authorUserName: message.author
      };

      this.props.receiveNotification(notification);
    }
  });
}

If a direct message arrives for a channel that is not the current active channel, a notification is displayed until the user visits the channel.

lax image

Users are able to create direct message channels with multiple participants, which allows for private, team chats that are not accessible by other users. In the direct message creation modal, users are able scroll and select chat participants by clicking or by searching via the input field. Because all registered users are fetched on component mount and stored as part of the front-end state, the search does not have to fire off multiple AJAX requests to query the database each time the search string changes. To provide users with a better experience and more information when choosing direct message participants, each users status is displayed and updated in real-time as users log in and log out.

lax image

Optimized Data Handling

To ensure good responsiveness, selective AJAX requests are used to fetch only the data for the current active channel and processing, where necessary, is done mostly in the back-end to leverage the server's resources. In addition, eager loading through associations is used to avoid N+1 queries and to decrease the overhead associated with connecting to the database multiple times. In the case of messages, which are a frequently fetched resource as users browse channels, the includes method is used to eagerly fetch each message's user association so that the database is not hit multiple times when the data is required in the jbuilder view.

def index
  @messages = @chatroom.messages.includes(:user)
  render 'api/messages/index'
end

Note: Implementing the above optimization decreased the ActiveRecord portion of fetching the largest channel by a factor of 10 on the production environment.

AWS S3 Storage

By using AWS S3 for storing avatar images uploaded by users, Lax is able to take advantage of Amazon’s CloudFront CDN service that accelerates web asset delivery through CDN caching, further adding to performance and responsiveness.

Future Direction

  • Message Search
  • Message Formatting
  • GIF Support
  • Emoticon Support

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published