ruby-on-railswistia

Rails - How to embed a wistia video dynamically through a form


I am making an e-learning platform and have a Course resource so I can add courses dynamically. I am now at the stage where I need to upload videos to each course, and I have decided to use wistia for this.

What I'm not sure about exactly is how can I Embed the videos that belong to each course directly through the Course form? I couldn't find documentation as to how to achieve this, so any help would be highly appreciated.

Example:-

I have this embed code from wistia:

<iframe src="//fast.wistia.net/embed/iframe/tk6picrt4k" allowtransparency="true" frameborder="0" scrolling="no" class="wistia_embed" name="wistia_embed" allowfullscreen mozallowfullscreen webkitallowfullscreen oallowfullscreen msallowfullscreen width="640" height="388"></iframe>
<script src="//fast.wistia.net/assets/external/E-v1.js" async></script>

Once I make a :video_url table in the database, how do I then make the above code work as intended if I paste it in a form box in the Create Course action and submit the form? and What data type should :video_url be?

Courses Controller:-

class CoursesController < ApplicationController
  before_action :set_course, only: [:show, :edit, :update, :destroy]
  before_action :set_grade
  respond_to :html


  def index
   @grades = Grade.all
   @courses = Course.where grade: params[:grade_id]
   respond_with(@course)
  end


  def show
   respond_with(@course)
  end


  def new
    @grade = Grade.find(params[:grade_id])
    @course = @grade.courses.new
    respond_with(@course)
  end


  def edit

  end


  def create
    @grade = Grade.find(params[:grade_id])
    @course = @grade.courses.build(course_params)
    if @course.save
      redirect_to grade_courses_path(@grade, @courses), notice: 'Successfully Created Course'
    else
      render action: 'new'
    end
  end


  def update
    @course.update(course_params)
    redirect_to grade_courses_path(@grade, @courses), :notice => "Successfully Updated Course"
  end


  def destroy
    @course.destroy
    redirect_to grade_courses_path(@grade, @courses), :notice => "Successfully Deleted Course"
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_course
      @course = Course.find(params[:id])
    end

    def set_grade
      @grade = Grade.find(params[:grade_id])
    end 

    # Never trust parameters from the scary internet, only allow the white list through.
    def course_params
      params.require(:course).permit(:title, :period, :description, :semester, :grade, :subject, :grade_id, :chapters_from, :chapters_to, :instructor, :price)
    end
end

_form.html.erb

<%= bootstrap_form_for [@grade, @course] do |f| %>
  <% if @course.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@course.errors.count, "error") %> prohibited this course from being saved:</h2>

      <ul>
      <% @course.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.select :subject, [["Math"], ["Physics"], ["Chemistry"], ["Science"], ["Biology"], ["English"], ["Arabic"], ["Social Studies"]], { label: "Subject"}, { class: "selectpicker" } %>
  </div>
  <div class="field">
    <%= f.text_field :instructor %>
  </div>
  <div class="field">
    <%= f.select :period, [["First"], ["Second"], ["Third"], ["Final"]], { label: "Period"}, { class: "selectpicker" } %>
  </div>
  <div class="field">
    <%= f.text_area :description %>
  </div>
  <div class="field">
    <%= f.select :semester, [["First"], ["Second"]], { label: "Semester"}, { class: "selectpicker" } %>
  </div>
  <div class="field">
    <%= f.number_field :chapters_from %>
  </div>
  <div class="field">
    <%= f.number_field :chapters_to %>
  </div>
  <div class="field">
    <%= f.number_field :price %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Solution

  • Inside your controller we have to permit the new attribute video_url to be set. Rails will handle updates/creates for it on its own:

    # Never trust parameters from the scary internet, only allow the white list through.
    def course_params
      params.require(:course).permit(:title, :period, :description, :semester, :grade, :subject, :grade_id, :chapters_from, :chapters_to, :instructor, :price, :video_url)
    end
    

    Inside your view where you have the static iframe:

    ...
    <iframe src="#{@course.video_url}" allowtransparency="true" frameborder="0" scrolling="no" class="wistia_embed" name="wistia_embed" allowfullscreen mozallowfullscreen webkitallowfullscreen oallowfullscreen msallowfullscreen width="640" height="388"></iframe>
    ...
    

    This will populate your view with the given video_url. Note, there's no exception handling if the video_url is NIL.

    Your video_url should be of datatype :string. That's sufficient for a simple URL :)

    Considering you already have a form to submit data for your course (To create, edit, update the course with information) you will just have to add another input field for the URL (video_url).


    Now that you provided the form, we can just add another input:

    <%= bootstrap_form_for [@grade, @course] do |f| %>
      <% if @course.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@course.errors.count, "error") %> prohibited this course from being saved:</h2>
    
          <ul>
          <% @course.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    
      <div class="field">
        <%= f.text_field :title %>
      </div>
      <div class="field">
        <%= f.select :subject, [["Math"], ["Physics"], ["Chemistry"], ["Science"], ["Biology"], ["English"], ["Arabic"], ["Social Studies"]], { label: "Subject"}, { class: "selectpicker" } %>
      </div>
      <div class="field">
        <%= f.text_field :instructor %>
      </div>
      <div class="field">
        <%= f.select :period, [["First"], ["Second"], ["Third"], ["Final"]], { label: "Period"}, { class: "selectpicker" } %>
      </div>
      <div class="field">
        <%= f.text_area :description %>
      </div>
      <div class="field">
        <%= f.select :semester, [["First"], ["Second"]], { label: "Semester"}, { class: "selectpicker" } %>
      </div>
      <div class="field">
        <%= f.number_field :chapters_from %>
      </div>
      <div class="field">
        <%= f.number_field :chapters_to %>
      </div>
      <div class="field">
        <%= f.number_field :price %>
      </div>
      <div class="field">
        <%= f.text_field :video_url %>
      </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    

    That should be it!


    If you already have a form as well as an existing controller, hit us up with more code and I will gladly edit my answer to give you more specific input.

    So far, this should be it and enough for you to work with :)

    --- If you still need something else, let us know.