Tải Video với Rails và Ziggeo (phần 2)

Ở phần này chúng ta sẽ tìm hiểu thêm về: các sự kiện của Ziggeo, kết nối với user, api,...

Các sự kiện

Ziggeo cung cấp một loạt các sự kiện Javascript mà bạn có thể dùng: play, pause, uploaded và camera_nosignal. Ví dụ: chúng ta hãy tạo thanh tiến trình tùy chỉnh cho biết quá trình tải lên video diễn ra như thế nào. Điều này rất dễ thực hiện với sự kiện upload_progress liên tục cho biết có bao nhiêu byte đã được tải lên cho đến hiện tại.

Trước tiên, thêm phần progress vào trang. Tôi đang sử dụng Bootstrap 4 để tạo kiểu, nhưng bạn có thể sử dụng bất kỳ khung công tác CSS nào hoặc viết phong cách riêng của bạn:

views/videos/new.html.erb

<!-- ... -->
<progress class="progress progress-striped hidden-xs-up" value="0" max="100"></progress>

Class hidden-xs-up sẽ ẩn thanh progress này trên tất cả các màn hình. Ngoài ra, bạn có thể chỉ cần thêm display: none.

Bây giờ thêm đoạn code CoffeeScript:

javascripts/videos.coffee

jQuery(document).on 'turbolinks:load', ->
  ZiggeoApi.Events.on "upload_progress", ( uploaded, total, data ) ->
    $('progress').removeClass('hidden-xs-up').attr 'value', (uploaded / total) * 100

ZiggeoApi là object toàn cầu có sẵn sau khi tải Ziggeo's JS. Số lượng đã được tải lên trên tổng số byte, nhân với 100 cho chúng ta một tỷ lệ phần trăm. Biến dữ liệu chứa thông tin về video đang được tải lên.

Đừng quên thêm file sau:

javascript/application.js

//= require videos

Một điều khác chúng tôi có thể làm là chuyển hướng người dùng đến trang chủ sau khi video được tải lên:

javascripts/videos.coffee

ZiggeoApi.Events.on "submitted", ( data ) -> window.location.href = '/'

Cũng lưu ý rằng Ziggeo cung cấp một số phương pháp có thể gọi được để thao tác người chơi và người tải lên.

Truy vấn API

Bây giờ các video có thể được tải lên, nhưng chúng ta không hiển thị chúng bất cứ đâu. Để tìm danh sách video đã tải lên, bạn có thể sử dụng gem Ziggeo mà chúng tôi đã đưa vào đầu bài viết.

Bạn chỉ cần khởi tạo client với 3 key trước đó và gọi các phương thức đã require:

videoscontroller.rb

# ...
def index
  ziggeo = Ziggeo.new(ENV['ZIGGEO_KEY'], ENV['ZIGGEO_SECRET'], ENV['ZIGGEO_ENCRYPTION'])
  @videos = ziggeo.videos.index
end

Phương thức index chấp nhận các đối số như giới hạn và bỏ qua để tùy chỉnh thêm yêu cầu. Kết quả là, biến @videos sẽ là một mảng hashes, trong đó mỗi hash là uid của video và các thông tin meta khác. Mảng này bây giờ có thể được hiển thị trên trang chính:

views/videos/index.html.erb

<h1>Videos</h1>

<%= link_to 'Add video', new_video_path %>

<%= render partial: 'video', collection: @videos, as: :video %>

Lưu ý rằng chúng ta không render @videos vì nó là một mảng đơn giản. Bây giờ render player trong một partial. Video sẽ được mở trong popup:

views/videos/video.html.erb

<div class="card">
  <div class="card-block">
    <ziggeo ziggeo-video='<%= video['token'] %>'
            ziggeo-width="320"
            ziggeo-height="240" ziggeo-popup>
    </ziggeo>
</div>

Trường token chứa mã chứa mã nhận dạng duy nhất của video.

Liên kết Video với Người dùng

Một chức năng phổ biến là cho phép mỗi người dùng có video riêng của họ. Tuy nhiên, hiện nay, video không có thông tin về người sở hữu chúng. Thật không may, không có trường đặc biệt nào lưu trữ thông tin này, nhưng nó có thể được giải quyết bằng cách sử dụng thẻ của video. Các thẻ được truyền theo dạng một chuỗi phân cách bằng dấu phẩy, sau đó chuyển thành mảng. Khi tải xuống các video sau, chúng ta sẽ chỉ đơn giản vượt qua tùy chọn thẻ.

Chúng ta có thể sử dụng id của người dùng làm thẻ, nhưng điều này không an toàn. Thay vào đó, hãy tạo ra một token duy nhất sau khi người dùng được tạo:

models/user.rb

# ...
before_create -> { self.uid = generate_uid }

private

def generate_uid
  loop do
    uid = Digest::MD5.hexdigest(self.email + self.created_at.to_s + rand(10000).to_s)
    return uid unless User.exists?(uid: uid)
  end
end

Đơn giản chúng ta chỉ tạo ra một hash MD5 dựa trên email của người dùng, ngày tạo và một số ngẫu nhiên. Mã thông báo này phải là duy nhất, vì vậy chúng tôi đảm bảo không có người dùng khác đã có nó.

Trường uid chưa tồn tại, do đó phải thêm vào:

$ rails g migration add_uid_to_users uid:string

Thêm index và unique: true cho trường uid:

db/migrate/xyzadduidtousers.rb

class AddUidToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :uid, :string
    add_index :users, :uid, unique: true
  end
end

Chạy migration:

$ rails db:migrate

Khi đã có uid, chúng ta có thể cài đặt token cho video.

views/videos/new.html.erb

<ziggeo ziggeo-limit="60"
        ziggeo-width="320"
        ziggeo-height="240"
        ziggeo-perms="allowupload"
        ziggeo-tags="<%= current_user.uid %>">
</ziggeo>

Bây giờ để chỉ cần tìm video của người dùng hiện tại:

videoscontroller.rb

# ...
def index
  ziggeo = Ziggeo.new(ENV['ZIGGEO_KEY'], ENV['ZIGGEO_SECRET'], ENV['ZIGGEO_ENCRYPTION'])
  @videos = ziggeo.videos.index(tags: current_user.uid)
end

Vấn đề với API của Ziggeo là không có cách nào để tìm những video được phê duyệt bởi người kiểm duyệt. Thật kỳ lạ, nhưng nhóm hỗ trợ Ziggeo đã xác nhận thông tin này. Tất nhiên, chúng ta có thể lọc các video được kiểm duyệt trong controller bằng cách sử dụng phương thức keep_if, nhưng nếu bạn muốn sử dụng phân trang, mọi thứ sẽ trở nên khá phức tạp. Vì vậy, tại sao chúng ta không thiết lập callback của máy chủ và lưu trữ thông tin của video trong cơ sở dữ liệu của riêng mình theo cách mà chúng ta thấy phù hợp? Hãy làm điều đó trong phần tiếp theo!

Kết thúc phần 2!

Thank you!

Tài liệu dịch: https://www.sitepoint.com/video-uploads-with-rails-and-ziggeo/