Tạo trang landing page với Sinatra, Google Spreadsheets và Ruby

Đôi khi bạn building một prototype hoặc một ứng dụng nội bộ đơn giản, bạn có thể không cần dùng đến database cho ứng dụng của mình. Sử dụng Google Spreadsheet có thể nhanh hơn và dễ dàng hơn trong việc cài đặt và hoạt động. Bài viết này mình giới thiệu ví dụ về việc dùng Sinatra Gem, Google SpreadsheetsRuby để tạo một landing page giống như Google Form và dữ liệu sau khi submit sẽ được lưu tại file của bạn trên Google Drive. Accessing your Spreadsheet Trước hết, bạn cần tạo một file spreadsheet trên Google Drive của mình, nhớ đặt tên tiêu đề cho file nhé!

Tạo một folder để build project mới:

$ mkdir ruby-google-sheets-sinatra
$ cd ruby-google-sheets-sinatra

Bạn cũng cần lấy thông tin xác thực OAuth2 để truy cập vào spreadsheet bằng Ruby bằng cách thực hiện các bước sau để tạo một tài khoản service:

  1. Truy cập trang Google APIs Console
  2. Tạo một project mới.
  3. Chọn Enable API. Tìm và enable Google Drive API.
  4. Tạo credentials cho Web Server để truy cập Application Data.
  5. Tạo service account và cấp cho nó quyền editor của Project Role.
  6. Download file JSON.
  7. Copy file JSON tới folder ruby-google-sheets-sinatra và đặt lại tên thànhclient_secret.json.

Đó là những thông tin cần thiết mà ứng dụng của bạn cần. Chúng đại diện cho một user, người mà có thể update file spreadsheet thay cho bạn. Chúng ta cũng cần cung cấp cho user này quyền truy cập vào file spreadsheet của bạn. Mở fileclient_secret.json, tìm và copy email của client_email và share file speadsheet của bạn cho email đã copy này.

Building with Sinatra and google_drive

  • Tạo file Gemfile trong folderruby-google-sheets-sinatra và thêm:

    #Gemfile 
    source "https://rubygems.org"
    
    gem "sinatra"
    gem "google_drive"
    
  • Chạy bundle install

  • Tạo trang index.erb để tạo form submit:

    #views/index.erb
    <div class="jumbotron">
      <div class="container">
        <div class="row">
          <div class="col-md-12">
            <h1>Fancy new app!</h1>
            <p>This is going to be really useful for you!</p>
          </div>
        </div>
        <div class="row iphone">
          <div class="col-md-4 col-sm-4">
            <% if defined? error_message %>
              <p class="bg-danger"><%= error_message %></p>
            <% end %>
            <% if defined? flash_message %>
              <p class="bg-success"><%= flash_message %></p>
            <% end %>
            <form action="/" method="POST">
              <div class="form-group">
                <label for="name">Name</label>
                <input type="text" class="form-control" name="name" id="name">
              </div>
              <div class="form-group">
                <label for="email">Email address</label>
                <input type="email" class="form-control" name="email" id="email">
              </div>
              <div class="form-group">
                <label for="phone_number">Phone number</label>
                <input type="tel" class="form-control" name="phone_number" id="phone_number">
              </div>
              <button type="submit" class="btn btn-primary">Submit</button>
            </form>
          </div>
        </div>
      </div>
    </div>
    
    #views/layout.erb
      <!DOCTYPE html>
     <html lang="en">
       <head>
         <meta charset="utf-8">
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
         <meta name="viewport" content="width=device-width, initial-scale=1">
    
         <title>Fancy new app!</title>
    
         <!-- Bootstrap -->
         <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
         <link rel="stylesheet" href="/app.css">
       </head>
       <body>
         <%= yield %>
    
         <div class="container">
           <hr>
           <footer>
             <p>&copy; 2017 The Fancy New App Company, Inc.</p>
           </footer>
         </div>
       </body>
     </html>
    
    # public/app.css
    .jumbotron{
     padding-bottom: 0;
    }
    
    .iphone {
     background: transparent url(/iphone.png) no-repeat center calc(100% + 350px);
     padding-bottom:300px;
    }
    
    @media (min-width: 768px) {
     .iphone {
       background: transparent url(/iphone.png) no-repeat 80% top;
       padding-bottom:48px;
     }
    }
    
    .bg-danger {
     padding: 15px;
    }
    
  • Tạo file app.rb và thêm:

    require("bundler")
    Bundler.require
    
    get "/" do
     erb :index
    end
    

    Sau khi lưu file, bạn có thể chạy app với lệnh ruby app.rb . Truy cập vào link http://localhost:4567/ bạn có thể thấy có một form và chúng ta sẽ dùng form này để thu thập dữ liệu người dùng và lưu lại trên file speadsheet của mình.

Saving data to Google Spreadsheets from Sinatra Chúng ta cần tạo một route để nhận params từ request Post từ form submit của người dùng và gửi chúng tới Google Speadsheet API. Tạo một helper method giúp chúng ta truy cập tới file speadsheet chúng ta muốn lưu:

#app.rb
def worksheet
  @session ||= GoogleDrive::Session.from_service_account_key("client_secret.json")
  @spreadsheet ||= @session.spreadsheet_by_title("for test app")
  @worksheet ||= @spreadsheet.worksheets.first
end

Phương thức nên bắt đầu với một session mới với Speadsheet API, mở sreadsheet bạn muốn lưu và chọn trang tính đầu tiên. Thay "for test app" bằng tên title của file spreadheest bạn muốn lưu. Ta sẽ thêm dữ liệu vào hàng cuối cùng của trang tính cộng với 1 hàng để nó luôn luôn được lưu vào spreadsheet:

#app.rb
post "/" do
  new_row = [params["name"], params["email"], params["phone_number"]]
  begin
    worksheet.insert_rows(worksheet.num_rows + 1, [new_row])
    worksheet.save
    erb :index, locals: {flash_message: "Your data saved"}
  rescue
    erb :index, locals: {
      error_message: "Your details could not be saved, please try again."
    }
  end
end

Chúng ta lấy các params truyền lên và biến chúng thành một mảng để đại diện cho một hàng. Tên hàng lấy từ thuộc tính name của các trường<input> tương ứng trong form. Lưu ý kiểu dữ liệu cho từng trường: text cho name, email cho emailtel cho phone_number.

Sử dụng worksheet.insert_rows để chèn dòng mới vào spreadsheet, lưu spreadsheet và hiển thị lại trang index với flash mesage đã lưu thành công.

Lưu file và khởi động lại server. Truy cập http://localhost:4567/ và nhập thông tin trên form. Nhấp vào gửi và bạn sẽ thấy nó xuất hiện trong spreadsheet của bạn. Thanks for reading!!!! Link app: https://github.com/phanbt58/ruby-google-sheets-sinatra Link tham khảo: https://www.twilio.com/blog/2017/03/create-a-landing-page-with-sinatra-google-spreadsheets-and-ruby.html


All Rights Reserved