Skip to content

Latest commit

 

History

History
441 lines (344 loc) · 11.2 KB

Develop_Rails_View_Application.md

File metadata and controls

441 lines (344 loc) · 11.2 KB

Develop your Rails Application with Action View

Let's start to build simple Rails application with Action View providing real-time communications in a private room. For example, create Rails application using Devise for user authentication.

Prepare Rails application

At first, create new Rails application:

$ rails new chime_view_app
$ cd chime_view_app

Add gems to your Gemfile:

# Gemfile

gem 'devise'
gem 'amazon-chime-sdk-rails'

Then, install devise:

$ bundle install
$ rails g devise:install
$ rails g devise User
$ rails g migration add_name_to_users name:string
$ rails g devise:views User

Update your application_controller.rb like this:

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end 
end

Add user name form to your app/views/users/registrations/new.html.erb view template like this:

# app/views/users/registrations/new.html.erb

<div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name, autocomplete: "name" %>
</div>

<div class="field">
  <%= f.label :email %><br />
  <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

Update devise configuration in devise.rb to use scoped views:

# config/initializers/devise.rb

Devise.setup do |config|
  # Uncomment and update
  config.scoped_views = true
end

Add login header to your application. Create new app/views/layouts/_header.html.erb and update your app/views/layouts/application.html.erb like this:

# app/views/layouts/_header.html.erb

<header>
  <div>
    <div>
      <strong>Rails Application for Amazon Chime SDK Meeting (Rails App with Action View)</strong>
    </div>
    <div>
      <% if user_signed_in? %>
        <%= current_user.name %>
        <%= link_to 'Logout', destroy_user_session_path, method: :delete %>
      <% else %>
        <%= link_to "Sign up", new_user_registration_path %>
        <%= link_to 'Login', new_user_session_path %>
      <% end %>
    </div>
  </div>
</header>
# app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Rails Application for Amazon Chime SDK Meeting</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= yield(:javascript_pack_tag) %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div id="app">
      <%= render 'layouts/header' %>
      <%= yield %>
    <div>
  </body>
</html>

Create private room functions

Create MVC by generator:

$ rails g scaffold room name:string
$ rails g scaffold entry room:references user:references
$ rake db:migrate

Update your room.rb like this:

# app/models/room.rb

class Room < ApplicationRecord
  has_many :entries, dependent: :destroy
  has_many :members, through: :entries, source: :user

  def member?(user)
    members.include?(user)
  end
end

Add uniqueness validation to your entry.rb like this:

# app/models/entry.rb

class Entry < ApplicationRecord
  belongs_to :room
  belongs_to :user
  # Add uniqueness validation
  validates :user, uniqueness: { scope: :room }
end

Update create and destroy method in your entries_controller.rb like this:

# app/controllers/entries_controller.rb

class EntriesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_room
  before_action :set_entry, only: [:destroy]

  # POST /entries
  # POST /entries.json
  def create
    @entry = Entry.new(entry_params)

    respond_to do |format|
      if @entry.save
        format.html { redirect_to @room, notice: 'Member was successfully added.' }
        format.json { render :show, status: :created, location: @room }
      else
        format.html { redirect_to @room, notice: @entry.errors }
        format.json { render json: @entry.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /entries/1
  # DELETE /entries/1.json
  def destroy
    @entry.destroy
    respond_to do |format|
      format.html { redirect_to @room, notice: 'Member was successfully removed.' }
      format.json { head :no_content }
    end
  end

  private
  # Use callbacks to share common setup or constraints between actions.
  def set_room
    @room = Room.find(params[:room_id])
  end

  # Use callbacks to share common setup or constraints between actions.
  def set_entry
    @entry = Entry.find(params[:id])
  end

  # Only allow a list of trusted parameters through.
  def entry_params
    params.require(:entry).permit(:room_id, :user_id)
  end
end

Develop meeting functions with amazon-chime-sdk-rails

Install amazon-chime-sdk-rails and generate your controllers by Controller Generator:

$ rails g chime_sdk:install
$ rails g chime_sdk:controllers -r room

Add and uncomment several functions in generated meetings_controller.rb and meeting_attendees_controller.rb for your app configurations:

# app/controllers/api/meetings_controller.rb

class MeetingsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_room
  before_action :check_membership

  include ChimeSdk::Controller::Meetings::Mixin

  private
  # Add
  def set_room
    @room = Room.find(params[:room_id])
  end

  # Add
  def check_membership
    unless @room.member?(current_user)
      message = 'Unauthorized: you are not a member of this private room.'
      redirect_to @room, notice: message
    end
  end

  # Uncomment
  def meeting_request_id
    "PrivateRoom-#{@room.id}"
  end

  # Uncomment
  def attendee_request_id
    "User-#{current_user.id}"
  end

  # Uncomment
  def application_meeting_metadata(meeting)
    {
      "MeetingType": "PrivateRoom",
      "PrivateRoom": @room
    }
  end

  # Uncomment
  def application_attendee_metadata(attendee)
    user_id = attendee[:Attendee][:ExternalUserId].split('-')[3]
    {
      "AttendeeType": "User",
      "User": User.find_by_id(user_id)
    }
  end

  # Uncomment
  def application_attendee_metadata(attendee)
    user_id = attendee[:Attendee][:ExternalUserId].split('-')[3]
    {
      "AttendeeType": "User",
      "User": User.find_by_id(user_id)
    }
  end
end
# app/controllers/api/meeting_attendees_controller.rb

class MeetingAttendeesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_room
  before_action :check_membership

  include ChimeSdk::Controller::Attendees::Mixin

  private
  # Add
  def set_room
    @room = Room.find(params[:room_id])
  end

  # Add
  def check_membership
    unless @room.member?(current_user)
      message = 'Unauthorized: you are not a member of this private room.'
      redirect_to @room, notice: message
    end
  end

  # Uncomment
  def attendee_request_id
    "User-#{current_user.id}"
  end

  # Uncomment
  def application_attendee_metadata(attendee)
    user_id = attendee[:Attendee][:ExternalUserId].split('-')[3]
    {
      "AttendeeType": "User",
      "User": User.find_by_id(user_id)
    }
  end
end

Bundle Amazon Chime SDK into single amazon-chime-sdk.min.js file and copy it to app/assets/javascripts by Single Javascript Generator in amazon-chime-sdk-rails:

$ rails g chime_sdk:js

Add amazon-chime-sdk.min.js to your Asset Pipeline:

# config/initializers/assets.rb

Rails.application.config.assets.precompile += %w( amazon-chime-sdk.min.js )

Then, generate meeting views by View Generator in amazon-chime-sdk-rails:

$ rails g chime_sdk:views

Simply customize your meeting view generated app/views/meetings/show.html.erb:

// app/views/meetings/show.html.erb

function showApplicationUserName(attendee) {
  // Comment
  // return attendee.Attendee.AttendeeId;
  // Uncomment
  return `${attendee.Attendee.ApplicationMetadata.User.name} (${attendee.Attendee.AttendeeId})`;
}

Add member management and meeting link to your room view:

# app/views/rooms/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @room.name %>
</p>

<p>
  <strong>Private Meeting:</strong>
  <p><%= link_to 'Show Meetings', room_meetings_path(@room) %></p>
  <p><%= link_to 'Join the Meeting', room_meetings_path(@room), method: :post %></p>
</p>

<p>
  <strong>Members:</strong>
  <table>
    <tbody>
      <% @room.entries.each do |entry| %>
        <tr>
          <td><%= entry.user.name %></td>
          <td><%= link_to 'Remove', [@room, entry], method: :delete, data: { confirm: 'Are you sure?' } %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
</p>

<p>
  <strong>Add members:</strong>
  <%= form_for [@room, Entry.new] do |f| %>
    <%= f.hidden_field :room_id, value: @room.id %>
    <%= f.collection_select :user_id, User.all, :id, :name %>
    <%= f.submit "Add" %>
  <% end %>
</p>

<%= link_to 'Edit', edit_room_path(@room) %> |
<%= link_to 'Back', rooms_path %>

Update your routes.rb like this:

# config/routes.rb

Rails.application.routes.draw do
  root "rooms#index"
  devise_for :users
  resources :rooms do
    resources :entries, only: [:create, :destroy]
    resources :meetings, only: [:index, :show, :create, :destroy] do
      resources :meeting_attendees, as: :attendees, path: :attendees, only: [:index, :show]
    end
  end
end

Note that you need to set up AWS credentials or IAM role for amazon-chime-sdk-rails. See Set up AWS credentials for more details.

Finally, start rails server:

$ rails s

Now ready to take off! Open http://localhost:3000/ in your browser. Sign up users from Sign up header. For example, sign up ichiro as ichiro@example.com and stephen as stephen@example.com. Then, create a new room and add ichiro and stephen as room members.

Now you can create a new meeting from room view.

default-meeting-view-created-image

After creating a new meeting from any private room, you can join the meeting from "Join the Meeting" button in your meeting view. Your rails application includes simple online meeting implementation using Amazon Chime SDK as a rails view.

default-meeting-view-joined-image

You can also customize your meeting view using Amazon Chime SDK for JavaScript. Enjoy your application development!