科技

以 Rails 7.0 開發最小可用產品(下)

Vendor Icon

CIO Taiwan

9月. 23, 2022

1200-04-dashboard

Covid-19 住院患者即時動態(下)

DevOps 的實踐是一種組織文化與哲學的轉變,其中對內外在環境的迅速應變也是一個非常重要的議題,在 Covid-19 疫情嚴峻之際,筆者特別以「Covid-19 住院患者即時動態」為例,以兩上、下期來介紹,醫院是如何用運 DevOps 工具快速解決管理及臨床人員的痛點。

文/鄭重男


Rials 像網頁系統開發者的魔法手套,除了本身具備的能力(Ruby)以外,更可以依需求加載數以萬計的寶石(RubyGems)來強化其他能力(開發的速度),由 RubyGems 官方網站(https://rubygems.org)可觀察到,下載次數超過一億次的寶石(Gems)竟多達 200 個之多,由此可見,在 Ruby 或 Rails 的開發領域中,有效學習及使用(收集)寶石,是 Rails(魔法手套)能力極致發揮的關鍵及優勢之一。

[ 推薦閱讀:Covid-19 住院患者即時動態(上)]

Rails 框架

上一期文章中我們提到了如何使用 Rails 來建立最小可用的專案,也約略提及開發前期部分常用的方法及 Git 的概念,在筆者還沒有接觸 Rails 框架開發系統前,曾經以為大家說的「用框架開發系統很快」就是建立(Create)一個專案(如,部落格系統,rails new blog)後,「部落格系統」就寫好了,如果真的連商業邏輯都不用寫就建好一個完整部落格系統,那就像不久前流行的一句話:「將來 AI 會取代(XXX)工作」一樣,系統開發者也許有可能也淪為 AI 眾多犧牲者之一吧!(透過深度學習的 AI,或許真的有機會走到這一步,目前已知 Github 的 Copilot 也開始提供部分類似的開發功能,如:主動提供下一行程式碼建議,或是提供樣板程式碼等),然而,在真正動手開發專案後,才知道原來心裡想的,其實不是那麼一回事。

Rails 框架,基本上是讓我們可以用一些命令語法(Linux-like 或 Microsoft-Windows-Subsystem-Linux,Command)簡單且快速地將 Rails 基本架構預先產生出來,開發人員便可在此架構上撰寫商業邏輯、前端介面(UI/UX)及資料表的設計。

Rails Scaffolding

回到開發最小可用產品這個主題,此專案一開始只有一個資料表,我們可依據已規劃好的資料表名稱(pcr)、欄位名稱及屬性,於建立 Rails 專案後,再於專案目錄內執行下列語法(如圖一所示)產生核酸檢驗的鷹架(scaffold)及資料遷移檔。

原檔版面-1
▲ 圖一 rails g scaffold 命令。(點圖放大)

這一段語法的意思是要讓 rails 產生一個名為 pcr 的鷹架(scaffold),成功執行後,Rails 便會以專案預設的模板(templates)建立一個(新增、讀取、更新、刪除,CRUD)的 MVC 架構。

Model

產生出來 model migration 檔,如下:

class CreatePcrs < ActiveRecord::Migration[7.0]    def change      create_table :pcrs do |t|        t.string :ca_inpseq        t.string :ca_medno        t.string :mh_name        t.string :ca_bedno        t.string :ca_vsdoccd        t.string :em_empname        t.string :mh_idno        t.string :ca_inpdate        t.string :lbh_culldate        t.string :lbd_repdate        t.string :lbh_diacode        t.string :lbd_state        t.float :positive_days          t.timestamps      end    end  end 

只要執行 rails db:migrate 之後,系統便會自動建立資料表及新增所有欄位及屬性,如(圖二)所示。

原檔版面-2
▲ 圖⼆ pcr 資料表及欄位屬性。(點圖放大)

如果你的系統只是簡單的讓使用者透過網頁操作此資料表的增、讀、修、刪動作,到這裡就可以收工了。或許你會納悶為何都沒有寫任何程式碼(難道是 NoCode?),也沒有碰到資料庫的(Structured Query Language,SQL)?其實不是,而是當我們用 Rails 產生鷹架(scaffold)時,裡面的模板機制會自動將相關的程式檔案通通產生出來,於是就讓人產生沒有寫程式碼的錯覺,其實這一切都是 Rails 的陰謀,筆者相信,有不少人就是被這些看似甜蜜的語法糖給騙進來的。

話說回來,一個系統的開發,不會只用固定的幾個欄位或一張資料表就足夠的,在迭代過程中,一定會碰到欄位修改及異動,當你想在資料表新增一個 boolean 欄位時,Rails 也提供了另一個指令代碼來產生對應的遷移檔,如:

rails g migration add_is_special_ward_to_pcr is_special_ward:boolean

若過程沒有任何錯誤,執行 rails db:migrate 之後,就會發現新的欄位已經被正確的產生出來了。

之前我們就曾經提過,在這種開發架構下的資料庫或資料表的遷移,也繼承 Rails 「約定優於設定原則」,所以,在處理資料庫 schema 的成本相對是較低的,無論原來的資料庫是在哪個遷移版次,下次執行遷移時,都會自動將沒執行過的遷移檔補足,因此,幾乎不會出現資料庫欄位不一致的問題。

提示:在產生任何遷移檔後,記得一定要執行 rails db:migrate 以執行資料庫的異動更新,否則執行網頁時便會出現錯誤。

[ 加入 CIO Taiwan 官方 LINE 與 Facebook ,與全球CIO同步獲取精華見解 ]

另外,專案中,我們還需要將原來存在於醫療資訊系統(HIS)資料庫的病患及檢驗相關資料,定時寫入在 Postgresql 的資料表(pcrs),因此,在擷取 HIS 資料時,常見會有兩種做法,一種是在原來的 HIS 端撰寫一個對應的 API,以 JOSN 或其他格式進行交換,另一種則是直接用 Rails 建立另一個資料庫連結,用 ORM 方式擷取 HIS 資料表內容,由於是在醫院內部開發且尚在資安可控的範疇,通常就會以後者的開發模式優先。

為了讓 Rails 可以順利連結兩個不同的資料庫,必須在 app/database.yml 資料庫設定檔中,增加一個 HIS 資料庫設定,便於連結 HIS 的資料庫,由於 Rails 預設的資料庫是 Postgresql ,所以,我們要增加一個處理 Oracle 資料庫連接的寶石(Gem)來處理並增加開發效率,如圖三所示。

原檔版面-3
▲ 圖三 新增資料庫連結設定。(點圖放大)

Views & Controllers

使用 Scaffold 建立程式時,除了產生 model 檔案外,也會同時建立使用者瀏覽器的顯示頁面 views 以及讓我們用來撰寫商業邏輯的 controller,也就是 MVC 架構。

由於一開始的使用者故事定義中,是設定每十分鐘擷取一次 HIS 的資料並寫入 Postgresql 資料庫,想當然爾,勢必要有一個排程工作來完成這個事情。

jobs 與 sidekiq 排程

● Job 工作

為了解決定時擷取HIS資料的問題,我們可以利用 Rails 的指令來產生一個工作(job),如:

rails g job get_his_pcr_data

執行後,Rails 便會在專案 jobs 目錄內產生一個名為 get_his_pcr_data_job.rb 的檔案,如:

# app/jobs/get_his_pcr_job.rb    class GetHisPcrDataJob < ActiveJob::Base    queue_as :default       def perform(*args)      #      # 從這裏開始寫 HIS 擷取相關資料並存入 postgresql 的 pcrs 資料表       #     end  end 

● Sidekiq 定時排程

sidekiq 是 Rails 專案中,常被拿來用於特定時間執行某一個事件的寶石(gem),它可以定時執行一次工作,因此,我們可以將上述的 job 直接設定給 sidekiq 執行,如:

# config/schedule.yml    job1:    cron: "*/10 * * * *"    class: "GetHisPcrDataJob"    queue: default    args: [] 

config/schedule.yml

job1:

cron: “*/10 * * * *”

class: “GetHisPcrDataJob”

queue: default

args: []

設定完成後,系統便會在每十分鐘執行一次 GetHisPcrDataJob 裡面的程式碼,至此,我們算是初步完成第一個版本的使用者故事核心邏輯了。

Deploy 發佈程序

最後一個階段,也就是發佈生產環境階段,由於我們希望系統未來可以進入 CI/CD pipeline 或最終以 kubernetes 來運行,因此用 docker 來建立專案的 image 是必需要的動作。

Dockerfile

docker image 在 DevOps 中是一個非常的重要角色,因此,我們必須先撰寫 Dockerfile 來產生專案的 image,產生出來的 image,會包含容器啟動時的作業系統、Rails 執行環境及其他網路設定等,礙於篇幅所限,有興趣的讀者,可自行到網路搜尋 rails Dockerfile 相關的範例檔案。

如果你目前尚無完整的 CI/CD 環境,可以把程式碼(含 Dockerfile)推到雲端的儲存庫中,如 Github 或 Gitlab 之類的服務,體驗一下 CI/CD pipeline 的流程及運作模式。如果你的環境暫時無法使用完整的 CI/CD 程序,也可以像筆者一樣,採用半自動的方式啟動 Rails 專案。

首先要用 docker 命令來建立專案的影像檔(image),如下:

docker build -t covid-19 .

一旦編譯完成,就可以用 docker images 來檢視編譯出來影像檔,如下:

covid-19                           latest            914b540a5a18   11  days ago     1.84GB 

docker-compose.yml

若決定要以 docker-compose 啟動 Rails 專案,那麼就要先建立 docker-compose.yml 檔案,如:

version: "3.9"  services:    db:      image: postgres      volumes:        - ./tmp/db:/var/lib/postgresql/data      environment:        POSTGRES_PASSWORD: db_password    app:      image: covid-19      command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p  3000 -b '0.0.0.0'"      volumes:        - .:/myapp      ports:        - "3000:3000"      depends_on:        - db    redis:      image: 'redis:alpine'      restart: always    sidekiq:      image: covid-19      environment:        -  DATABASE_URL=postgres://db_user:db_password@db/e_paper_card_production        - REDIS_URL_SIDEKIQ=redis://redis:6379        - RAILS_MASTER_KEY=${RAILS_MASTER_KEY}      depends_on:        - app        - db        - redis      command: bundle exec sidekiq 

撰寫完成後便可以利用下列指令啟動相關的服務:

docker-compose up -d

一旦啟動成功,使用者就可以由主機上的 3000 port 登入專案了,如:http://192.168.1.2:3000。

開發與測試環境(Development & Test)

就是開發者用來撰寫程式碼的環境(含除錯模式、單元及系統測試)等,通常是自己用的本機電腦,筆者所知的 Rails 開發者中,似乎也都以 MacOS 居多,不是因為蘋果電腦比較好,而又是另一種不成文的約定或習慣。一般來說,如果你周圍開發圈多數人採用的開發電腦,會直接影響新進入者的採用意向,為的只是避開一些可能連老鳥都沒碰過的坑。

預備環境 (Staging)

就算是同樣的環境,有時因為資料的差異或因為版本發佈太過於頻繁,可能會直接影響正式生產環境的正常運作,因此,若有個 Staging 預備環境作為緩衝或預先驗證是否衍生其他問題後,再發佈到正式生產環境以避免不必要的服務中斷。

生產環境 (Production)

經過前述幾個階段環境測試無誤後,就可以發佈到正式的生產環境,以 DevOps 來說,就是將這些過程以自動化的方式運作,盡可能減少人為介入,也是我們說的持續發佈(CI/CD)的最後一哩路了。不過,在實務上,如果組織尚不具備完全自動化的持續交付環境時,仍可依組織的資源及環境做適度調整。


(本文授權非營利轉載,請註明出處:CIO Taiwan)

內容來源

author avatar
CIO Taiwan
IDG集團的媒體品牌CIO於1987年創刊,為國際性最權威的IT管理專業雜誌。擁有全球最頂尖的IT管理專家作者群,因此能寫出最權威的分析評論、最先進的IT管理觀念。
donate plan

充電計畫

喜歡這篇文章嗎?歡迎幫作者充電,好內容值得更多人支持

瞭解詳情