何怡璇 熊棠 易修文



摘要:在Linux系統中,使用Ruby on Rails 5框架設計一個基于Web的數據導入工具。將Excel數據導入任意數據庫中,并可定義導入策略。
關鍵詞:數據導入;Ruby on Rails 5
中圖分類號:TP311 ? ? ?文獻標識碼:A
文章編號:1009-3044(2020)17-0046-03
數據的批量導入是系統設計和使用中經常都會遇到的問題,特別是采用Excel工具收集和處理之后的數據,如何導入至業務系統數據庫并能正確應用于系統,是系統設計人員必須考慮的。使用數據庫管理工具進行數據導入對操作人員技能有較高要求,且存在數據安全風險。同時,部分數據還存在不同表之間的關聯需求,使用數據庫管理工具導入就需要對這樣的數據進行預先處理,或者編寫SQL語句實現。
這就提出一個需求,設計一個Web界面的數據導入工具,具有界面友好、可定制保存策略、可視化、支持關聯表等功能,以滿足一般用戶的使用需求。
在Linux系統中,使用Ruby on Rails 5框架設計一個數據導入工具,使其具有上述功能特定。
1 系統環境
Ruby on Rails 5框架本身支持Windows、Linux、MacOS等系統環境,且使用對象關系映射(ORM)技術實現了數據庫類型不可知[1],在代碼編寫時注意避免直接使用SQL語句,就能實現一套系統在不同數據庫之間的自由轉換[2]。測試環境為Ubuntu16.04操作系統,Rails 5.2.3,MySQL 5.7數據庫。
2 過程分析
2.1 策略列表
用戶應可看到之前已保存的策略列表,可選擇根據已有策略導入或者新建策略。
2.2 上傳文件
不論用戶使用哪種方式,均需上傳源數據文件。客戶端、服務器端應對文件類型進行過濾,僅接受可識別的文件,如xlsx、csv等。
2.3 讀取數據
文件上傳之后,應讀取出文件中的數據,并顯示。如果文件有多個工作表,應顯示出來,并支持人工選擇。
2.4 定義策略
如使用已有策略,應將策略展示在頁面上并支持修改;如為新建策略,應支持可視化定義策略并支持自動匹配。新建策略及修改策略應保持UI的一致性。
2.5 保存策略并導入數據
新建策略應可選擇是否保存,使用已有策略且發生策略更改時,應更新并持久化。不論策略是否保存,均應按當前策略導入數據并持久化。
3 模型設計
策略需要持久化保存,創建Rule類用來保存策略。
3.1 Rule類的屬性
Rule類用來存儲策略并可再次使用。至少應包含兩個字段。
3.1.1 title字段
title字段用于識別策略,便于再次使用。
3.1.2 pattern字段
pattern字段用于存儲策略文本。策略為JSON格式的文本數據,利于在前端、應用層中保持一致性,且便于存儲。
3.2 pattern格式
pattern是整個工具的核心,用來定義如何導入數據。
3.2.1 src
src鍵值對用來定義數據源,即上傳文件中的第幾個工作表,從0開始。
3.2.2 dest
dest鍵值對用來定義數據目的,即系統中對應的ActiveRecord對象。
3.2.3 f_r
部分文件第一行為表頭。第一行是表頭還是數據應交由用戶判斷,f_r鍵值對用來定義第一行是否為表頭。
3.2.4 map
map鍵值對用來定義源數據中的字段與ActiveRecord對象各屬性的映射關系。因存在多個字段,其值為一個數組。數組的每個元素均為多個鍵值對組成的JSON格式對象。
3.2.4.1 col
col鍵值對用來定義該位置字段對應的ActiveRecord對象屬性名。
3.2.4.2 type
type鍵值對用來定義該位置字段對應的ActiveRecord對象屬性的字段類型。不同的字段類型在導入時會做特定的處理。
3.2.4.3 not_unique
not_unique鍵值對用來定義該位置字段對應的值在數據庫中是否要求唯一性。
3.2.4.4 to_rel
to_rel鍵值對用來定義該位置字段對應的值是否存在表關聯。如此值為false,則以下幾個鍵值對可以不做定義。
3.2.4.5 rel_table
rel_table鍵值對用來定義該位置字段關聯表的ActiveRecord對象名。
3.2.4.6 rel_col
rel_col鍵值對用來定義該位置字段關聯的ActiveRecord對象的對應屬性。
3.2.4.7 rel_col_type
rel_col_type鍵值對用來定義該位置字段關聯的ActiveRecord對象的對應屬性的字段類型。不同的字段類型在導入時會做特定的處理。
3.2.4.8 rel_c_rol
rel_c_rol鍵值對用來定義建立表關聯時返回的字段。
3.2.4.9 rel_c_rol_type
rel_c_rol_type鍵值對用來定義返回對應字段的字段類型。不同的字段類型在導入時會做特定的處理。
3.2.4.10 rel_not_unique
rel_not_unique鍵值對用來定義該位置字段關聯的ActiveRecord對象的對應屬性值在數據庫中是否要求唯一性。
4 控制與視圖
文件上傳之后,控制器調用組件讀取文件內容。
4.1 讀取源數據
使用開源Gem Roo執行所有常見的電子表格類型的讀訪問權限,包括Excel、LibreOffice、OpenOffice、CSV、Google spreadsheets等格式[3]。
對于Excel 2013文件,使用Roo::Excelx.new((服務器端文件路徑))可以讀出文件中的數據內容賦值給實例@data_src,并可按工作表進行訪問。@data_src.sheets以數組形式輸出各工作表名; @data_src.sheet(i).parse()可將第i個工作表以數組形式輸出,如該表沒有數據,則輸出nil。
4.2 編寫策略
為了便于對策略進行可視化編寫,首先需要把讀取的源數據按工作表以Table樣式輸出在頁面上。如果數據量較大,可部分輸出。
通過ApplicationRecord類的descendants方法可以獲得系統已有的ActiveRecord對象及屬性列表。
通過以上準備工作即可建立控制面板,用于編寫策略。
4.2.1 數據源及目的表
采用下拉菜單的方式選擇源數據及目的表。源數據即文件中的第幾個工作表,目的表即數據要以哪個ActiveRecord對象導入數據庫。同時要有首行導入選項。
4.2.2 字段映射
當數據源、目的表選定之后,根據數據源數組的列數生成對應選項下拉菜單。當“第一行包含標題”復選框未選中時,按Excel習慣,按字母標識列;當前述復選框被選中時,應根據名稱進行自動對應。默認狀態下字段導入是允許重復的。
4.2.3 關聯表
當對應字段的“關聯表”選項被選中時,將出現更多選項。目標表即被關聯的表,目標域即數據將要被導入的域。默認狀態下字段導入是不允許重復的,返回的值為id;通過打開更多選項,能對上述兩個設定進行修改。當選擇返回域時,應根據原目標表目標域的類型進行限制,防止因用戶操作失誤造成數據類型不匹配。
4.2.4 數據類型
數據類型是根據ActiveRecord對象讀取,不能被人為控制。
4.2.5 生成策略并提交
頁面上有一個隱藏的表單元素pattern_text,值為pattern的JSON格式文本。
為了統一新建與編輯策略時的腳本,應在頁面載入時使用JSON.parse方法將pattern_text的值序列化為JSON實例pattern;若pattern_text的值為空或不是JSON格式文本,將其賦值為“{}”后再執行前述操作。生成前述選項時,如果pattern相應的值為null或undefined,則按默認值生成;否則讀入該值,并按值設置。
完成設置后,點擊“導入”按鈕,再次運行策略生成腳本,根據各控件的值對pattern相應的鍵值對賦值;然后使用JSON.stringify方法將pattern轉化為字符串并賦值給pattern_text,然后提交后臺保存。為了便于日后再次調用,此處應設置保存選項。
4.3 數據持久化
策略文本提交到后臺,如要保存為模板,則按Rule類保存。
策略在被使用前,需要再次序列化為JSON對象。JSON的統一規則使前/后端保持了很好的統一性。
依然使用Roo得到的數組,并根據pattern[“src”]的值獲得需要導入的數據數組@src。對@src進行遍歷,每一個元素存為一條數據庫中的記錄。遍歷時根據pattern[“f_r”]的值決定是否導入@src[0]。
4.3.1 構造參數散列式
構造一個空散列式_params = {}用來記錄參數。
4.3.2 字段映射
遍歷@src[i]的每一個元素,如@src[i][j],按以下步驟進行導入操作。
4.3.2.1 是否關聯
讀取pattern[“map”][j][“to_rel”],如非,則直接導入,否則按關聯導入并返回值導入。
4.3.2.2 關聯導入
根據pattern[“map”][j][“rel_table”]、pattern[“map”][j][“rel_col”]確定ActiveRecord對象及字段,如pattern[“map”][j][“rel_not_unique”]為否,則按字段、值搜索,如有結果,則返回對象實例@rel;否則按pattern[“map”][j][“rel_table”]新建ActiveRecord對象實例@rel,并賦值保存。最后返回 @rel.attributes[pattern[“map”][j][“rel_c_rol”]]的值_value。
4.3.2.3 字段賦值
不管是直接導入還是關聯,都牽涉到字段賦值。目標字段根據pattern[“map”][j][“col”]、pattern[“map”][j][“rel_col”]確定,值需要根據pattern[“map”][j][“type”]、pattern[“map”][j][“rel_col_ type”]進行預先處理。如轉換成字符串型、浮點型、日期型等。如為關聯導入按前述執行得到值_value,否則將處理之后的值賦為_value。
4.3.2.4 更新參數散列式
使用merge方法將{ pattern[“map”][j][“col”].to_sym => _vlue}合并入_params,至此則完成了一個字段的處理。
4.3.3 構造對象實例并保存
根據pattern[“dest”]獲取ActiveRecord對象,使用create方法和_params參數執行存儲。至此一條完成的記錄按策略完成了導入。
4.4 根據策略模板導入
前述策略如果保存為模板,可以再次使用,上傳文件后讀取模板中的策略,并按策略設置控制面板。系統應可檢查提交后的模板策略是否應被更新并安最新策略執行導入。
5 結束語
該工具能夠實現可視化定制、保存策略,并支持表關聯,達到了設計要求。但還存在只能單字段關聯,不支持多個字段確定表關聯的問題,將在后續進行改進。
參考文獻:
[1] Active Record 基礎[EB/OL].[2019-12-20].https://ruby-china.github.io/rails-guides/active_record_basics.html.
[2] 對象關系映射-維基中文鏡像,自由的百科全書[EB/OL]. [2019-12-20].https://zh.wikipedia.com/wiki/對象關系映射.
[3] Documentation for roo (2.8.3) [EB/OL]. [2019-12-20].https://www.rubydoc.info/gems/roo/2.8.3.
【通聯編輯:謝媛媛】