2018/1/11

第二十四天:認識資料庫(續)

昨天我們講到資料模型產生器的用法:

rails generate model keyword_mapping keyword message

會產生兩個我們需要的檔案:

  • 資料庫遷移檔:db/migrate/20180110181744_create_keyword_mappings.rb
  • 資料模型:app/models/keyword_mapping.rb

其中,資料庫遷移檔就像是一張對資料庫施法的卷軸設計圖,可以用來幫資料庫升級。

那要怎麼升級呢?

資料庫遷移

使用 rails db:migrate 指令就會進行資料庫升級。

D:\只要有心,人人都可以作卡米狗\ironman>rails db:migrate
== 20180110181744 CreateKeywordMappings: migrating ============================
-- create_table(:keyword_mappings)
   -> 0.4916s
== 20180110181744 CreateKeywordMappings: migrated (0.4927s) ===================


D:\只要有心,人人都可以作卡米狗\ironman>

還可以用 rails db:rollback 降級:

D:\只要有心,人人都可以作卡米狗\ironman>rails db:rollback
== 20180110181744 CreateKeywordMappings: reverting ============================
-- drop_table(:keyword_mappings)
   -> 0.5057s
== 20180110181744 CreateKeywordMappings: reverted (0.5211s) ===================


D:\只要有心,人人都可以作卡米狗\ironman>

可以用 rails db:migrate:status 查看目前等級。這是升級前:

D:\只要有心,人人都可以作卡米狗\ironman>rails db:migrate:status

database: D:/只要有心,人人都可以作卡米狗/ironman/db/development.sqlite3

 Status   Migration ID    Migration Name
--------------------------------------------------
  down    20180110181744  Create keyword mappings


D:\只要有心,人人都可以作卡米狗\ironman>

這是升級後:

D:\只要有心,人人都可以作卡米狗\ironman>rails db:migrate:status

database: D:/只要有心,人人都可以作卡米狗/ironman/db/development.sqlite3

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20180110181744  Create keyword mappings


D:\只要有心,人人都可以作卡米狗\ironman>

資料庫已就緒,接下來就只等我們把學習紀錄寫入了。接下來我會試著用 Google 試算表來比喻目前資料庫的狀態(因為我家沒有 Excel),現在的資料庫看起來像這樣:

資料模型

我們可以使用 rails console 或簡寫 rails c 去試著操作看看資料模型, rails console 是一個類似 irb 的互動式介面,他可以讓你輸入一行程式就立即生效。

D:\只要有心,人人都可以作卡米狗\ironman>rails console
Loading development environment (Rails 5.1.4)
irb(main):001:0>

列出所有資料

我們的資料模型叫做 KeywordMapping。可以用 .all 將它顯示出來看看:

irb(main):001:0> KeywordMapping.all
  KeywordMapping Load (2.5ms)  SELECT  "keyword_mappings".* FROM "keyword_mappings" LIMIT ?  [["LIMIT", 11]]
=> #<activerecord::relation []="">
irb(main):002:0>

這一段:

SELECT  "keyword_mappings".* FROM "keyword_mappings" LIMIT ?

是我們對資料庫進行查詢的 SQL 語法,幸好你不需要學會這個,就當作沒看到吧。

而這一段:

=> #<activerecord::relation []="">

是指 KeywordMapping.all 是一個 ActiveRecord::Relation 類別的實體, [] 表示它是空的。

讓我們弄點東西進去。

新增資料

KeywordMapping.new 可以獲得一筆新的空白資料。

irb(main):002:0> new_data = KeywordMapping.new
=> #<keywordmapping id:="" nil,="" keyword:="" message:="" created_at:="" updated_at:="" nil="">
irb(main):003:0>

用一個變數 new_data 去接住它,因為我們接下來要對他做事。

irb(main):003:0> new_data.keyword = "Q"
=> "Q"

設定 new_data 的 keyword 是 "Q"。

irb(main):004:0> new_data.message = "A"
=> "A"
irb(main):005:0>

設定 new_data 的 message 是 "A"。

都設定好之後用 new_data.save 來存檔。

irb(main):005:0> new_data.save
   (0.0ms)  begin transaction
  SQL (494.1ms)  INSERT INTO "keyword_mappings" ("keyword", "message", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["keyword", "Q"], ["message", "A"], ["created_at", "2018-01-11 14:30:55.567172"], ["updated_at", "2018-01-11 14:30:55.567172"]]
   (52.5ms)  commit transaction
=> true
irb(main):006:0>

一樣,就是一堆不需要看懂的 SQL。現在使用 KeywordMapping.all 就能看到新加入的資料了。

目前資料表的狀態:

irb(main):006:0> KeywordMapping.all
  KeywordMapping Load (0.0ms)  SELECT  "keyword_mappings".* FROM "keyword_mappings" LIMIT ?  [["LIMIT", 11]]
=> #<activerecord::relation [#<keywordmapping="" id:="" 1,="" keyword:="" "q",="" message:="" "a",="" created_at:="" "2018-01-11="" 14:30:55",="" updated_at:="" 14:30:55"="">]>
irb(main):007:0>

新增資料也有簡寫的方式可以一行做完,指令是 KeywordMapping.create({keyword:"Q2", message:"A2"})

irb(main):007:0> KeywordMapping.create(keyword:"Q2", message:"A2")
   (0.0ms)  begin transaction
  SQL (485.4ms)  INSERT INTO "keyword_mappings" ("keyword", "message", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["keyword", "Q2"], ["message", "A2"], ["created_at", "2018-01-11 14:36:34.858893"], ["updated_at", "2018-01-11 14:36:34.858893"]]
   (48.5ms)  commit transaction
=> #<keywordmapping id:="" 2,="" keyword:="" "q2",="" message:="" "a2",="" created_at:="" "2018-01-11="" 14:36:34",="" updated_at:="" 14:36:34"="">
irb(main):008:0>

這是傳入一個 hash 作為設定,用 create 方法的話就會自動 save,所以就不用自己再打 save 了。

目前資料表的狀態:

irb(main):009:0> KeywordMapping.all
  KeywordMapping Load (0.0ms)  SELECT  "keyword_mappings".* FROM "keyword_mappings" LIMIT ?  [["LIMIT", 11]]
=> #<activerecord::relation [#<keywordmapping="" id:="" 1,="" keyword:="" "q",="" message:="" "a",="" created_at:="" "2018-01-11="" 14:30:55",="" updated_at:="" 14:30:55"="">, #<keywordmapping id:="" 2,="" keyword:="" "q2",="" message:="" "a2",="" created_at:="" "2018-01-11="" 14:36:34",="" updated_at:="" 14:36:34"="">]>
irb(main):010:0>

查詢資料

我們通常不會想要拿出整個資料表,而是只想要查當中的一筆,這時候就要用 where 方法,以下示範 KeywordMapping.where(keyword:"Q2")

irb(main):008:0> KeywordMapping.where(keyword:"Q2")
  KeywordMapping Load (0.5ms)  SELECT  "keyword_mappings".* FROM "keyword_mappings" WHERE "keyword_mappings"."keyword" = ? LIMIT ?  [["keyword", "Q2"], ["LIMIT", 11]]
=> #<activerecord::relation [#<keywordmapping="" id:="" 2,="" keyword:="" "q2",="" message:="" "a2",="" created_at:="" "2018-01-11="" 14:36:34",="" updated_at:="" 14:36:34"="">]>
irb(main):009:0>

這是篩選功能,我們對 keyword 欄位做 Q2 篩選,在 Google 試算表按照順序點就可以達到相同的效果。

篩選出來可能會有多筆,我們可以 .all 取得全部或者 .first 取第一筆,或 .last 取最後一筆。

所以卡米狗觸發教學的寫法是這樣:KeywordMapping.where(keyword:"Q2").last.message,對 keyword 欄位做篩選,找到最後一次教學紀錄,然後取出 message 欄位的內容。

irb(main):012:0* KeywordMapping.where(keyword:"Q2").last.message
  KeywordMapping Load (0.5ms)  SELECT  "keyword_mappings".* FROM "keyword_mappings" WHERE "keyword_mappings"."keyword" = ? ORDER BY "keyword_mappings"."id" DESC LIMIT ?  [["keyword", "Q2"], ["LIMIT", 1]]
=> "A2"
irb(main):013:0>

丟 Q2 進去資料庫查,查到 A2 再回應給 Line。

本日重點

  • 學會使用資料庫遷移
  • 學會使用資料模型
  • 了解卡米狗觸發教學的原理

明天會講怎麼用這兩天學到的東西做出卡米狗學習指令。

沒有留言: