如何建立 Ruby on Rails 應用程式

簡介

Rails 是一個用 Ruby 編寫的網路應用框架。它採取了一種有主見的開發方式,假設在有共同目標的情況下,設定的慣例最能服務開發者。因此,Rails 提供了處理路由、狀態數據、資產管理等的慣例,以提供大多數網路應用程式所需的基礎功能。

Rails 遵循 模型-視圖-控制器(MCV)架構模式,將應用程式的邏輯(位於模型中)與應用程式資訊的路由和呈現分開。這種組織結構——以及其他允許開發者將程式碼提取到 輔助方法部分模板 的慣例——確保應用程式代碼不會不必要地重複

在本教程中,您將建立一個 Rails 應用程式,讓使用者能夠發布有關鯊魚及其行為的資訊。這將是未來應用程式開發的良好起點。

先決條件

要跟隨本教程,您需要:

  • 一台運行 Ubuntu 18.04 的本地機器或開發伺服器。您的開發機器應具有具備管理權限的非 root 用戶,並且配置了 ufw 防火牆。如需設置指南,請參閱我們的 Ubuntu 18.04 初始伺服器設置 教程。
  • Node.jsnpm 安裝在您的本地機器或開發伺服器上。本教程使用 Node.js 版本 10.16.3 和 npm 版本 6.9.0。有關在 Ubuntu 18.04 上安裝 Node.js 和 npm 的指南,請遵循 如何在 Ubuntu 18.04 上安裝 Node.js 中“使用 PPA 安裝”部分的指示。
  • Ruby、rbenv 和 Rails 已安裝在您的本地機器或開發伺服器上,按照 如何在 Ubuntu 18.04 上使用 rbenv 安裝 Ruby on Rails 中的步驟 1-4 進行操作。本教程使用 Ruby 2.5.1、rbenv 1.1.2 和 Rails 5.2.0

步驟 1 — 安裝 SQLite3

在創建我們的 Rails shark 應用程式之前,我們需要確保有一個資料庫來存儲用戶數據。Rails 預設配置為使用 SQLite,這在開發中通常是一個不錯的選擇。由於我們的應用程式數據不需要高級的程式擴展性,SQLite 將能滿足我們的需求。

首先,更新您的套件索引:

  1. sudo apt update

接著,安裝 sqlite3libsqlite3-dev 套件:

sudo apt install sqlite3 libsqlite3-dev

這將安裝 SQLite 及其所需的開發文件。

檢查版本以確認安裝成功:

  1. sqlite3 --version
Output
3.22.0 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt1

安裝好 SQLite 後,您就可以開始開發您的應用程式了。

第二步 — 創建一個新的 Rails 項目

安裝好數據庫後,我們可以創建一個新的 Rails 項目,並查看 Rails 通過 rails new 命令給我們的一些默認樣板代碼。

使用以下命令創建一個名為 sharkapp 的項目:

  1. rails new sharkapp

你將看到大量輸出,告訴你 Rails 為你的新項目創建了什麼。下面的輸出突出顯示了一些重要的文件、目錄和命令:

Output
create . . . create Gemfile . . . create app . . . create app/controllers/application_controller.rb . . . create app/models/application_record.rb . . . create app/views/layouts/application.html.erb . . . create config create config/routes.rb create config/application.rb . . . create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb . . . create config/database.yml create db create db/seeds.rb . . . run bundle install . . . Bundle complete! 18 Gemfile dependencies, 78 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. . . . * bin/rake: Spring inserted * bin/rails: Spring inserted

這裡突出顯示的輸出告訴你 Rails 已經創建了以下內容:

  • Gemfile:這個文件列出了你的應用程序的 gem 依賴項。一個 gem 是一個 Ruby 軟件包,而 Gemfile 允許你管理項目的軟件需求。
  • appapp 目錄是你的主要應用程序代碼所在的地方。這包括構成應用程序本身的模型、控制器、視圖、資產、助手和郵件程序。Rails 為 MVC 模型提供了一些應用程序級別的樣板代碼,以開始在文件如 app/models/application_record.rbapp/controllers/application_controller.rbapp/views/layouts/application.html.erb 中。
  • config:此目錄包含您應用程式的配置設定:
    • config/routes.rb:您的應用程式路由宣告存放在此檔案中。
    • config/application.rb:應用程式元件的通用設定位於此檔案中。
  • config/environments:此目錄存放各環境的配置設定。Rails 預設包含三個環境:developmentproductiontest
  • config/database.yml:資料庫配置設定位於此檔案中,分為四個部分:defaultdevelopmentproductiontest。由於 rails new 命令附帶的 Gemfile 包含了 sqlite3 gem,我們的 config/database.yml 檔案已將 adapter 參數設為 sqlite3,指定我們將使用 SQLite 資料庫與此應用程式。
  • db:此資料夾包含一個名為 migrate 的資料庫遷移目錄,以及 schema.rbseeds.rb 檔案。schema.db 包含您的資料庫資訊,而 seeds.rb 是您放置資料庫種子資料的地方。

最後,Rails 執行 bundle install 命令來安裝您 Gemfile 中列出的依賴項。

一旦設定完成,請導航至 sharkapp 目錄:

  1. cd sharkapp

您現在可以使用 rails server 命令啟動 Rails 伺服器,以確保您的應用程式正常運作。如果您在本地機器上工作,請輸入:

  1. rails server

Rails 預設綁定到 localhost,因此您現在可以通過在瀏覽器中導航至 localhost:3000 來訪問您的應用程式,您將看到以下圖像:

如果您在開發伺服器上工作,首先確保允許在端口 3000 上的連接:

  1. sudo ufw allow 3000

然後使用 --binding 標誌啟動伺服器,以綁定到您的伺服器 IP:

  1. rails server --binding=your_server_ip

在您的瀏覽器中導航至 http://your_server_ip:3000,您將看到 Rails 歡迎訊息。

一旦您瀏覽完畢,您可以通過按下 CTRL+C 來停止伺服器。

在您的應用程式創建並就位後,您已準備好從 Rails 模板開始構建,以創建一個獨特的應用程式。

步驟 3 — 搭建應用程式框架

為了創建我們的鯊魚資訊應用程式,我們需要創建一個模型來管理應用程式數據,視圖來啟用用戶與該數據的交互,以及一個控制器來管理模型和視圖之間的通信。為了構建這些內容,我們將使用 rails generate scaffold 命令,該命令將為我們提供一個模型、一個數據庫遷移來更改數據庫模式、一個控制器、一套完整的視圖來管理創建、讀取、更新和刪除(CRUD)操作,以及部分模板、助手和測試。

由於 generate scaffold 命令為我們做了很多工作,我們將仔細查看它創建的資源,以理解 Rails 在幕後所做的工作。

我們的 generate scaffold 指令將包含我們模型的名稱以及我們希望在資料庫表中包含的欄位。Rails 使用 Active Record 來管理應用程式資料(以模型對象構建)與應用程式資料庫之間的關係。我們的每個模型都是一個 Ruby 類別,同時也繼承自 ActiveRecord::Base 類別。這意味著我們可以像操作 Ruby 類別一樣操作我們的模型類別,同時還能引入 Active Record 的方法。Active Record 隨後會確保每個類別對應到資料庫中的一個表,每個類別的實例對應到該表中的一行。

輸入以下指令來生成一個 Shark 模型、控制器及相關視圖:

  1. rails generate scaffold Shark name:string facts:text

通過 name:stringfacts:text,我們向 Rails 提供了關於希望在資料庫表中包含的欄位及其應接受的數據類型的信息。兩者都提供了輸入空間,但 text 允許更多的字符來記錄鯊魚的事實。

當你輸入此指令時,你將再次看到一長串輸出,解釋 Rails 為你生成的所有內容。以下輸出突顯了對我們設置來說比較重要的部分:

Output
invoke active_record create db/migrate/20190804181822_create_sharks.rb create app/models/shark.rb . . . invoke resource_route route resources :sharks invoke scaffold_controller create app/controllers/sharks_controller.rb invoke erb create app/views/sharks create app/views/sharks/index.html.erb create app/views/sharks/edit.html.erb create app/views/sharks/show.html.erb create app/views/sharks/new.html.erb create app/views/sharks/_form.html.erb . . .

Rails 已經在 app/models/shark.rb 創建了模型,並為其生成了相應的數據庫遷移文件:db/migrate/20190804181822_create_sharks.rb。您的遷移文件上的時間戳將與此處顯示的不同。

此外,它還創建了一個控制器 app/controllers/sharks_controller.rb,以及與我們應用程序 CRUD 操作相關的視圖,這些視圖收集在 app/views/sharks 下。在這些視圖中,有一個部分視圖 _form.html.erb,包含跨視圖使用的代碼。

最後,Rails 在 config/routes.rb 中添加了一個新的資源路由 resources :sharks。這使得 Rails 路由器能夠將傳入的 HTTP 請求與 sharks 控制器及其相關視圖匹配。

雖然 Rails 已經為我們完成了大量應用程序代碼的構建工作,但查看一些文件以了解正在發生的事情仍然值得。

首先,讓我們使用以下命令查看控制器文件:

  1. cat app/controllers/sharks_controller.rb
Output
class SharksController < ApplicationController before_action :set_shark, only: [:show, :edit, :update, :destroy] # GET /sharks # GET /sharks.json def index @sharks = Shark.all end # GET /sharks/1 # GET /sharks/1.json def show end # GET /sharks/new def new @shark = Shark.new end # GET /sharks/1/edit def edit end # POST /sharks # POST /sharks.json def create @shark = Shark.new(shark_params) respond_to do |format| if @shark.save format.html { redirect_to @shark, notice: 'Shark was successfully created.' } format.json { render :show, status: :created, location: @shark } else format.html { render :new } format.json { render json: @shark.errors, status: :unprocessable_entity } end end end # PATCH/PUT /sharks/1 # PATCH/PUT /sharks/1.json def update respond_to do |format| if @shark.update(shark_params) format.html { redirect_to @shark, notice: 'Shark was successfully updated.' } format.json { render :show, status: :ok, location: @shark } else format.html { render :edit } format.json { render json: @shark.errors, status: :unprocessable_entity } end end end # DELETE /sharks/1 # DELETE /sharks/1.json def destroy @shark.destroy respond_to do |format| format.html { redirect_to sharks_url, notice: 'Shark was successfully destroyed.' } format.json { head :no_content } end end private # 使用回調來在動作之間共享通用設置或約束。 def set_shark @shark = Shark.find(params[:id]) end # 永遠不要信任來自可怕網際網路的參數,只允許白名單通過。 def shark_params params.require(:shark).permit(:name, :facts) end end

控制器負責管理資訊如何被獲取並傳遞到其相關模型,以及如何與特定視圖關聯。如您所見,我們的 sharks 控制器包含了一系列方法,大致對應於標準的CRUD操作。然而,為了在錯誤情況下提高效率,這些方法比CRUD功能更多。

例如,考慮 create 方法:

~/sharkapp/app/controllers/sharks_controller.rb
. . .
  def create
    @shark = Shark.new(shark_params)

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

如果成功保存了 Shark 類的新實例,redirect_to 將生成一個新的請求,該請求隨後會被導向到控制器。這將是一個 GET 請求,並由 show 方法處理,向用戶展示他們剛剛添加的鯊魚。

如果失敗,Rails將再次渲染 app/views/sharks/new.html.erb 模板,而不是向路由器發出另一個請求,給用戶再次提交數據的機會。

除了鯊魚控制器之外,Rails還為我們提供了一個index視圖模板,該模板對應於我們控制器中的index方法。我們將使用此視圖作為應用程序的根視圖,因此值得一看。

輸入以下內容以輸出文件:

  1. cat app/views/sharks/index.html.erb
Output
<p id="notice"><%= notice %></p> <h1>Sharks</h1> <table> <thead> <tr> <th>Name</th> <th>Facts</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @sharks.each do |shark| %> <tr> <td><%= shark.name %></td> <td><%= shark.facts %></td> <td><%= link_to 'Show', shark %></td> <td><%= link_to 'Edit', edit_shark_path(shark) %></td> <td><%= link_to 'Destroy', shark, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New Shark', new_shark_path %>

index視圖遍歷我們的Shark類的實例,這些實例已經映射到我們數據庫中的sharks表。使用ERB模板,視圖輸出與單個鯊魚實例關聯的表中的每個字段:namefacts

然後,視圖使用link_to助手創建一個超鏈接,提供的字符串作為鏈接文本,提供的路徑作為目的地。這些路徑是通過我們在使用rails generate scaffold命令定義sharks資源路由時可用的助手實現的。

除了查看我們的index視圖外,我們還可以查看new視圖,了解Rails如何在視圖中使用部分模板。輸入以下內容以輸出app/views/sharks/new.html.erb模板:

  1. cat app/views/sharks/new.html.erb
Output
<h1>New Shark</h1> <%= render 'form', shark: @shark %> <%= link_to 'Back', sharks_path %>

雖然這個模板看似缺少新增鯊魚條目的輸入欄位,但render 'form'的引用告訴我們,模板正在引入_form.html.erb局部模板,該模板提取了跨視圖重複的代碼。

查看該文件將讓我們全面了解如何創建新的鯊魚實例:

  1. cat app/views/sharks/_form.html.erb
Output
<%= form_with(model: shark, local: true) do |form| %> <% if shark.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(shark.errors.count, "error") %> prohibited this shark from being saved:</h2> <ul> <% shark.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.label :name %> <%= form.text_field :name %> </div> <div class="field"> <%= form.label :facts %> <%= form.text_area :facts %> </div> <div class="actions"> <%= form.submit %> </div> <% end %>

此模板使用了form_with表單助手。表單助手旨在通過特定模型的欄位和範圍,方便地從用戶輸入創建新對象。在此,form_with接受model: shark作為參數,其創建的新表單構建器對象具有與sharks表中的欄位相對應的輸入欄位。因此,用戶有欄位可以輸入鯊魚的name和鯊魚的facts

提交此表單將創建一個包含用戶數據的JSON響應,您的應用程序的其他部分可以通過params方法訪問該數據,該方法創建一個包含該數據的ActionController::Parameters對象。

現在您已經知道rails generate scaffold為您生成了什麼,您可以繼續為您的應用程序設置根視圖。

步驟 4 — 創建應用程式根視圖並測試功能

理想情況下,您希望應用程式的登陸頁面對應於應用程式的根目錄,以便用戶能夠立即了解應用程式的用途。

有多種方法可以處理這個問題:例如,您可以創建一個 Welcome 控制器和一個相關的 index 視圖,這將為用戶提供一個通用的登陸頁面,也可以連結到應用程式的不同部分。然而,在我們的情況下,讓用戶登陸到我們的 index 鯊魚視圖將足以作為應用程式用途的介紹。

為了設置這一點,您需要在 config/routes.rb 中修改路由設置以指定應用程式的根目錄。

使用 nano 或您喜歡的編輯器打開 config/routes.rb 進行編輯:

  1. nano config/routes.rb

該文件將如下所示:

~/sharkapp/config/routes.rb
Rails.application.routes.draw do
  resources :sharks
  # 有關此文件中可用的 DSL 詳細信息,請參閱 http://guides.rubyonrails.org/routing.html
end

如果沒有設置更特定的內容,http://localhost:3000http://your_server_ip:3000 的默認視圖將是默認的 Rails 歡迎頁面。

為了將應用程式的根視圖映射到 sharks 控制器的 index 視圖,您需要在文件中添加以下行:

~/sharkapp/config/routes.rb
Rails.application.routes.draw do
  resources :sharks

  root 'sharks#index' 
  # 有關此文件中可用的 DSL 詳情,請參閱 http://guides.rubyonrails.org/routing.html
end

現在,當用戶導航到您的應用程式根目錄時,他們將看到一個完整的鯊魚列表,並有機會創建新的鯊魚條目,查看現有條目,以及編輯或刪除特定條目。

完成編輯後保存文件並退出編輯器。如果您使用 nano 編輯文件,可以按 CTRL+XY,然後按 ENTER

您現在可以使用以下命令運行遷移:

  1. rails db:migrate

您將看到確認遷移的輸出。

再次啟動 Rails 伺服器。如果您在本地工作,輸入:

  1. rails s

在開發伺服器上,輸入:

  1. rails s --binding=your_server_ip

如果您在本地工作,導航到 localhost:3000,或者如果您在開發伺服器上工作,導航到 http://your_server_ip:3000

您的應用程式登陸頁面將如下所示:

要創建一個新的鯊魚,點擊頁面底部的 New Shark 連結,這將帶您到 sharks/new 路由:

讓我們添加一些演示信息來測試我們的應用程式。在 Name 欄位中輸入“Great White”,在 Facts 欄位中輸入“Scary”:

點擊 Create 按鈕來創建鯊魚。

這將引導你進入 show 路由,這要歸功於 before_action 過濾器,它通過 set_shark 方法設置,該方法抓取我們剛剛創建的鯊魚的 id

~/sharkapp/app/controllers/sharks_controller.rb
class SharksController < ApplicationController
  before_action :set_shark, only: [:show, :edit, :update, :destroy]

  . . . 

  def show
  end

  . . . 

  private
    # 使用回調在動作之間共享通用設置或約束。
    def set_shark
      @shark = Shark.find(params[:id])
    end
  . . .

你可以通過點擊你的鯊魚條目上的 編輯 來測試編輯功能。這將帶你進入該鯊魚的 edit 路由:

將大白鯊的 facts 從“可怕”改為“巨大”,然後點擊 更新鯊魚。這將帶你回到 show 路由:

最後,點擊 返回 將帶你到更新後的 index 視圖:

現在你已經測試了應用程序的基本功能,你可以添加一些驗證和安全檢查,使一切更加安全。

第五步 — 添加驗證

你的鯊魚應用程序可以接受用戶輸入,但想像一種情況,用戶試圖創建一條沒有添加事實的鯊魚,或者為已經在數據庫中的鯊魚創建一個條目。你可以通過在模型中添加驗證來創建機制,以在數據進入數據庫之前檢查數據。由於應用程序的邏輯位於其模型中,在這裡驗證數據輸入比在應用程序的其他地方進行更有意義。

請注意,本教學不會涵蓋編寫驗證測試,但您可以透過查閱Rails 文件來了解更多關於測試的資訊。

如果您還未停止伺服器,請繼續輸入 CTRL+C 來停止它。

打開您的 shark.rb 模型文件:

  1. nano app/models/shark.rb

目前,該文件告訴我們 Shark 類繼承自 ApplicationRecord,而後者又繼承自ActiveRecord::Base

~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
end

首先,讓我們為 name 欄位添加一些驗證,以確認該欄位已填寫且該條目是唯一的,防止重複條目:

~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
  validates :name, presence: true, uniqueness: true
end

接下來,為 facts 欄位添加驗證,以確保它也已填寫:

~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
  validates :name, presence: true, uniqueness: true
  validates :facts, presence: true
end

我們在這裡不太關心事實的唯一性,只要它們與獨特的鯊魚條目相關聯即可。

完成後,保存並關閉文件。

再次啟動您的伺服器,使用 rails srails s --binding=your_server_ip,取決於您是在本地工作還是使用開發伺服器。

導航至您的應用程式根目錄,位於 http://localhost:3000http://your_server_ip:3000

點擊新增鯊魚。在表單中,將「大白鯊」添加到名稱欄位,並將「大牙齒」添加到事實欄位,然後點擊創建鯊魚。你應該會看到以下警告:

現在,讓我們看看是否能檢查其他驗證。點擊返回返回首頁,然後再次點擊新增鯊魚。在新表單中,在名稱欄位輸入「虎鯊」,並將事實留空。點擊創建鯊魚將觸發以下警告:

通過這些更改,您的應用程序已經設置了一些驗證措施,以確保保存到數據庫中的數據的一致性。現在您可以將注意力轉向應用程序的用戶,並定義誰可以修改應用程序數據。

步驟 6 — 添加身份驗證

有了驗證措施,我們對保存到數據庫的數據有了一些保障。但用戶呢?如果我們不希望任何用戶都能添加數據到數據庫,那麼我們應該添加一些身份驗證措施,以確保只有授權用戶可以添加鯊魚。為此,我們將使用http_basic_authenticate_with方法,這將允許我們創建用戶名和密碼組合來驗證用戶。

在 Rails 中,有多種方式可以驗證用戶,包括使用 bcryptdevise 這些 gem。然而,目前我們將在應用程式的控制器中添加一個方法,該方法將適用於整個應用程式的操作。這對於未來如果我們添加更多控制器到應用程式中將非常有用。

再次停止你的伺服器,使用 CTRL+C

打開定義你的 ApplicationController 的檔案:

  1. nano app/controllers/application_controller.rb

在裡面,你會看到 ApplicationController 類的定義,這是應用程式中其他控制器的父類:

~/sharkapp/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
end

為了驗證用戶,我們將使用一個硬編碼的用戶名和密碼,並通過 http_basic_authenticate_with 方法來實現。將以下代碼添加到檔案中:

~/sharkapp/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  http_basic_authenticate_with name: 'sammy', password: 'shark', except: [:index, :show]
end

除了在這裡提供用戶名和密碼之外,我們還通過指定不需要驗證的路由來限制驗證:indexshow。另一種實現方式是寫成 only: [:create, :update, :destroy]。這樣,所有用戶都能夠查看所有的鯊魚並閱讀特定鯊魚的資料。然而,在修改網站內容時,用戶需要證明他們有訪問權限。

在更健壯的設置中,您不會希望以這種方式硬編碼值,但為了演示目的,這將讓您了解如何為應用程序的路由包含身份驗證。它還讓您了解 Rails 默認情況下如何在 cookie 中存儲會話數據:一旦您在指定操作上進行身份驗證,您將無需在同一會話中再次進行身份驗證。

編輯完成後保存並關閉 app/controllers/application_controller.rb。現在您可以測試身份驗證的實際效果了。

使用 rails srails s --binding=your_server_ip 啟動服務器,並在瀏覽器中導航到您的應用程序,地址為 http://localhost:3000http://your_server_ip:3000

在登陸頁面上,點擊 New Shark 按鈕。這將觸發以下身份驗證窗口:

如果您輸入添加到 app/controllers/application_controller.rb 中的用戶名和密碼組合,您將能夠安全地創建一個新的鯊魚。

現在,您擁有一個功能齊全的鯊魚應用程序,包含數據驗證和基本身份驗證方案。

結論

您在本教程中建立的 Rails 應用程式是一個起點,您可以利用它進行進一步的開發。如果您有興趣探索 Rails 生態系統,專案文件是一個絕佳的入門之地。

您也可以透過閱讀如何在 Ruby on Rails 應用程式中創建嵌套資源來了解更多關於向您的專案添加嵌套資源的知識,這將展示如何建立應用程式的模型和路由。

此外,您可能還想探索如何使用React等框架為您的專案設置更為強大的前端。如何使用 React 前端設置 Ruby on Rails 專案提供了進行此操作的指導。

若您想探索不同的數據庫選項,亦可參閱如何在Ubuntu 18.04上將PostgreSQL與您的Ruby on Rails應用程式搭配使用,該指南詳述了如何使用PostgreSQL而非SQLite進行操作。此外,您還可查閱我們的PostgreSQL教程庫,以深入瞭解此數據庫的使用方法。

Source:
https://www.digitalocean.com/community/tutorials/how-to-build-a-ruby-on-rails-application