RealTimeWeekly | Building a Realtime Quiz with PubNub
16930
single,single-post,postid-16930,single-format-standard,ajax_fade,page_not_loaded,,qode-theme-ver-5.9,wpb-js-composer js-comp-ver-4.3.4,vc_responsive
 

Building a Realtime Quiz with PubNub

Receiving answers from the quiz app questions

18 Oct Building a Realtime Quiz with PubNub

martin lagrangeThe following tutorial is a Guest Post from Martin Lagrange (@supertinou), a developer evangelist at PubNub.

Building a Realtime Quiz with Ruby on Rails, ReactJS & PubNub

In this tutorial, we will learn how to build a realtime quiz app with Ruby On Rails and ReactJS using PubNub. We’ll walk through how to build an app that enables users to create a quiz session, invite other users, let the quiz owner start the session, let the participants all play the quiz in unison, and display the results at the end.

The image below shows the completed app. On the left side of the screen, you’ll see the participants list is displayed (this list is updated in realtime as users enter and leave the app). On the right side of the screen an activity feed is displayed.

A realtime quiz app built using Ruby, ReactJS and PubNub

The full open source repository is available here, and a live demo of the realtime quiz is available here.

To create the app, we will be using:

react ruby pubnub

  • Ruby on Rails: to create the quizzes and the sessions, send the questions, collect the answers and display the results
  • PubNub: to send and receive the data in realtime.
  • ReactJS: easily display and refresh the realtime data received from the PubNub Network.

Bootstrap Application

Before starting we will need to have a simple Rails app that allows a user to:

  • Create quizzes with multiple questions answers
  • Create quiz sessions with multiple participants

The features of the app will need to look like…

Demo Screencast:

The completed real time quiz app

UML Diagram:

Design pattern for building the realtime quiz app

Realtime Functionality for the Quiz

In the next steps, we are going to add realtime functionality to the bootstrap application. Here are the features we will implement step by step:

  • Each participant can get a secure link to play the quiz session.
  • The participants can see who is online / offline
  • The owner of the quiz can start the quiz and the questions are sent to the participants every 30 seconds.
  • The participant can answer the questions and see who has answered correctly/incorrectly in realtime.
  • The participants can see the results.

To build these features in our application, we’ll be using several PubNub channels:

The PubNub channels used for the real time quiz app

Step 1: PubNub Account and API Keys

To get your unique publish/subscribe keys, you’ll first need to sign up for a PubNub account. Once you sign up, you can get your unique PubNub keys in the PubNub Developer Dashboard. Our free Sandbox tier should give you all the bandwidth you need to build and test your app with the PubNub API.

Once you create your application, activate the Access Manager and Presence features in your Admin Dashboard.

Step 2: Setup of PubNub in your application

2.1 Setting up the dependencies

→ In the Gemfile, add the Ruby and Javascript PubNub client:

and run bundle install

→ In application.js add the following so it compiles to the asset pipeline:

The PubNub ruby gem allows to use the PubNub framework by initializing the pubnub instance through this way :

2.2 Creating a PubNub Singleton

In order to prevent the creation of multiple instances of the PubNub client in our application, and prevent the copying and pasting of the configuration keys throughout our application, we can create a PubNub singleton:

→ In app/lib create a file named pubnub_singleton.rb and copy/paste the following content:

Set the PubNub keys environment variables. In Rails 4.1+ put them in secrets.yml or use a gem such as dotenv

Then we we can easily use PubNub in this way in our application:

Step 3: Granting Unique Quiz Access

Granting unique quiz access in the PubNub powered realtime quiz

In this step, we’ll walkthrough how to grant unique quiz session access for the participants that you can share with them.

3.1 Create the Route to Access the Session

Each participant will be able to access the sessions through a dedicated link:

accessing the unique quiz links

→ In config/routes.rb, add a route for the participant to access the session:

→ Create a QuizSessions controller quiz_sessions_controller.rb :

→ In application_helper.rb add the following helper to allow the build the quiz session link from a participant object:

Next, use it to display the link dedicated to a participant in the participant list (as in the above screenshot) :

→ Create a file named show.html.erb in app/views/quiz_sessions/

The quiz owner can now share the quiz session links to the participant. You can now access the participant quiz session link but it’s blank.

Next, let’s create the backbone of our main JavaScript that will be the heart of our realtime quiz application.

3.2 Setting up the Backbone of the Quiz App

→ Create a quiz.js.coffee.erb file and past the following content:

Passing configuration data from the controller to the .js file

As you can see, we missed some main config information in our quiz.js.coffee.erb file and we need to get them from the QuizSessions controller. In Rails, it can be tricky to pass variables from controller to a JavaScript files. That’s why we are going to use the gon gem to make it easier:

→ In your Gemfile add:

and run bundle install

→ In application.html.erb add:

→ In the show method in quiz_sessions_contoller.rb you can now set variables to be passed to JavaScript files quiz.js.coffee.erb file :

and that we can easily get back in our quiz.js.coffee.erb file like that:

→ Replace the missing values in the constructor method of quiz.js.coffee.erb:

3.3 Restricting and Granting Access to the Different Channels

Restricting and granting access to different pubnub channels

We will be using the Access Manager feature provided by PubNub to make the channels private and grant specific rights (read / write) to specific users.

  • When we create the session, we first need to forbid access to all the session channels to disallow everyone to publish or subscribe to messages.
  • Then we need to set to the session (through a reserved auth key) full rights to all the channel for the application in order to be able later to subscribe and publish messages:

→ In session.rb add:

Note that in this case we use,the http_sync: true statement to ensure that the grant actions callbacks will be executed in the proper order.

→ In participant.rb add:

Step 4: Building the Realtime Participant List

Realtime Quiz Structure

As you may have noticed the application is composed of three different features. In this section, we’ll focus on the realtime participant list, our list of users that updates the online/offline status of connected users in realtime.  We will be using the Presence feature provided by PubNub to see which participants are online in the channel.

4.1 The ParticipantList Component

Below is how the Participant List looks like:

Realtime participant list

You can get the source of the ParticipantList ReactJS Component here.

→ Include the sources in your application and setup React in you Rails app using the react-rails gem

→ In show.html.erb add:

4.2 Integrating with PubNub

4.2.1 Display the online participants

The PubNub API allows you to request the list of people who are online on a specific channel, called here_now.

→ In quiz.js.coffee.erb just add the following method:

and call it in the constructor:

You can now see the list of online participants.

4.2.2 Subscribe to the Chat Channel and Update the Status and Info of the Participants

Here, when we are connecting the participant to the chat channel dedicated to the session, we are passing some data (its name and its email) using the state method. We are also updating the status of the participant when it is changing.

→ In quiz.js.coffee.erb add the following methods:

and call it in the constructor:

4.2.3 Pre-render the List of All the Participants (optional)

Optionally, you can render the list of all the participants even if they are not connected yet to the chat (A black icon will be displayed for their availability) :

You may want to pre-build you React component like this:

→ In show.html.erb, add :

→ In the show method of quiz_sessions_controller.rb :

Step 5: Send and Receive the Questions

In this step, we will implement the feature that will allow the quiz owner to start the quiz and send the questions to each participants.

5.1 Start the Quiz and Send the Questions from the Rails app:

Sending and receiving messages in our realtime quiz app

→ Add a start route for the session resource and a start method in sessions_controller.rb and call the @session.start! method from it.

→ Add a current_question_index field to the session. We will need it to know which question is currently displayed.

→ Add the rufus-scheduler gem in your Gemfile. We will need it to schedule the sending of the questions.

→ In session.rb we will implement the start! method, copy/paste the following:

→ In question.rb add the format method to display the question with the answers:

5.2 Display and Answer the Question:

Quiz Question and Answer

Questions are sent every 30 seconds through the server channel. We will display them in our JavaScript app and allow the participant to answer the question:

→ In quiz.js.coffee.rb' add the following methods:

and Include the React component which is displaying the questions.

→ In show.html.erb add :

5.3 Receive the Answers of the Participants in the Rails app:

Receiving answers from the quiz app questions

Now that the participant send their answers to the questions through the client channel, we will need to intercept them in the Rails app:

→ In session.rb just add:

We will want to store the answers sent by the participants:

→ Add a ParticipantAnswer model in order to save the answers of the participants:

→ In session.rb, update the handle_question_answer method:

→ In participant.rb, add:

Step 6: Displaying the Activity feed

Realtime activity feed

6.1 The Activity Feed Component:

→ Get the source of the ActivityFeed component here and include it in your application.

→ In show.html.erb

6.2 Adding the login/logout events

→ In quiz.js.coffee.erb Just add the following in the presence callback, and that’s all.

6.3 Adding the Answering Events

To display the people who have answered the question correctly or incorrectly in the activity feed, we need to check it in the app and send a proper answer event through the client channel

→ In session.rb, update the handle_question_answer method to add this when a question is answered:

Displaying in the App:

In quiz.js.coffee in the serverCallback method, add the following to displaying answering event :

Feel free to send more events!

6.4 Display a Success Notification:

Let’s take the opportunity that we are receiving the answering events to display a success notification whether your answer is correct or not:

Get the source of the SuccessNotifier component here and update the serverCallback method :

Step 7: Display the Quiz Results

We’re almost done! The last thing we need to do is create a quiz results scoreboard.

Realtime Quiz Results Scoreboard

→ Get the source of the ResultsDisplay component.

→ In session.rb implements the finish method which is already called once the last question is finishing displaying.

→ In quiz.js.coffee in the serverCallback method, add:

And that’s it! Congratulations, you’ve built your very own realtime quiz game. Like what you see? Check out our wide variety of other tutorials on the PubNub blog, or shoot us a tweet @PubNub with what you think!

 

  • Pingback: RealTimeWeekly | RealTimeWeekly #102()

  • Pingback: Coding (Other) | Pearltrees()

  • Qobiljon Ergashev

    what do “I” and “N” mean in your UML Diagram?

    • http://www.twitter.com/supertinou Martin Lagrange

      For instance : [QUIZ]–1———N–[QUESTION] means that a quiz has many questions and a question belongs only to one quiz. By the way, In UML class diagrams the star sign “*” is more commonly used to represent the many relationships.

      • Qobiljon Ergashev

        Thank you very much, Martin!

  • Qobiljon Ergashev

    What data type should I use in my migration for access_key, authorization_key, authorization_password? Because as I know from your link for LiveQuiz that they may contain digits and letters at the same time (like 1f2fc35449cf1eac). Thanx in advance!

    • http://www.twitter.com/supertinou Martin Lagrange

      The fields authorization_key and authorization_password are strings but you could use integers as long as these fields are unique.

  • Batman

    Question for martin, I want to create a quiz, where the answers are unknown until a specific time. For example. Who will win in a foot race? John or Jim? The race happens, and then the answer is given and updated. Would it be hard to tweak this tutorial to a live answer? In other words, all questions are given but the answers are updated real time.

    • http://www.twitter.com/supertinou Martin Lagrange

      It shouldn’t be that hard ;) In other words, you would like to add questions on the fly while the quiz is running ? Who will add the questions ? The quiz owner or the participants? What would be the flow, can you give more details ?

  • Carlos Cuesta Callejas

    why in ruby not working event message receiver?