iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 15
1

過去兩天我們分別介紹了Django與Laravel的console模式與基礎ORM操作
今天我們回過頭講解Phoenix的部分

首先,進入介面的指令如下:

$ iex -S mix
Erlang/OTP 20 [erts-9.0.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.5.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 

為了後續操作方便,我們會先對想要操作的Model取個別名

iex(1)> alias Hello.User
Hello.User

這樣接下來就可以直接使用User

新增

來試著新增一個空的user

iex(2)> changeset = User.changeset(%User{}, %{})
#Ecto.Changeset<action: nil, changes: %{},
 errors: [name: {"can't be blank", [validation: :required]},
  email: {"can't be blank", [validation: :required]}], data: #Hello.User<>,
 valid?: false>

會得到提示:nameemail不可為空
驗證是設定在User Model的changeset當中

接著我們把必填欄位補上

iex> params = %{name: "Joe Example", email: "joe@example.com"}
iex> changeset = User.changeset(%User{}, params)
#Ecto.Changeset<action: nil,
 changes: %{email: "joe@example.com", name: "Joe Example"}, errors: [],
 data: #Hello.User<>, valid?: true>

其實回傳值當中已經可以觀察到valid?: true
但我們依然可以用驗證的方法確認是否通過驗證

iex> changeset.valid?
true

但是到目前為止
這個changeset只存在記憶體當中
我們接下來要把它存入資料庫

iex> alias Hello.{Repo, User}
iex> Repo.insert(changeset)
[debug] QUERY OK db=2.0ms
INSERT INTO "users" ("email","name","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["joe123@example.com", "Joe Example", {{2017, 12, 18}, {9, 11, 4, 672407}}, {{2017, 12, 18}, {9, 11, 4, 672420}}]
{:ok,
 %Hello.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  email: "joe123@example.com", id: 2,
  inserted_at: ~N[2017-12-18 09:11:04.672407], name: "Joe Example",
  updated_at: ~N[2017-12-18 09:11:04.672420]}}

這樣就可以把剛剛的changeset存進去
你可以觀察他自動產生的SQL字串,基本上就是一般的SQL insert
包含了預設的時間戳記
也可以直接把user 欄位資料寫在insert內
這個時候不會檢查必填

iex> Repo.insert(%User{email: "user1@example.com"})

所以這樣依然會新增成功

查詢

來檢查一下剛剛新增的內容:

iex> Repo.all(User)
[debug] QUERY OK source="users" db=1.6ms
SELECT u0."id", u0."email", u0."name", u0."inserted_at", u0."updated_at" FROM "users" AS u0 []
[%Hello.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  email: "user1@example.com", id: 1,
  inserted_at: ~N[2017-12-18 09:10:01.857415], name: nil,
  updated_at: ~N[2017-12-18 09:10:01.859647]},
 %Hello.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  email: "joe123@example.com", id: 2,
  inserted_at: ~N[2017-12-18 09:11:04.672407], name: "Joe Example",
  updated_at: ~N[2017-12-18 09:11:04.672420]}]

可以看到剛剛新增的兩筆資料

假如我們不需要全部的欄位,只需要Email

iex> import Ecto.Query
iex> Repo.all(from u in User, select: u.email)
["user1@example.com", "joe123@example.com"]

會以array的方式回傳
括號內類似SQL的語法稱為DSL

實務上,查詢會另外寫

iex> query = from u in User, select: u.name
iex> Repo.all(query)
[nil, "Joe Example"]

query 可以疊加重組,自由度相當高

iex> query = from u in query

假如只需要取第一個寫入的資料

iex> query = from u in User
iex> Repo.one(first(query, :inserted_at))
[debug] QUERY OK source="users" db=1.7ms
SELECT u0."id", u0."email", u0."name", u0."inserted_at", u0."updated_at" FROM "users" AS u0 ORDER BY u0."inserted_at" LIMIT 1 []
%Hello.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
 email: "user1@example.com", id: 1, inserted_at: ~N[2017-12-18 09:10:01.857415],
 name: nil, updated_at: ~N[2017-12-18 09:10:01.859647]}

按照Elixir的語法,也可以改寫如下

iex> query |> first(:inserted_at) |> Repo.one

參考資料:
https://github.com/mydearxym/phoenix-doc-in-chinese/blob/master/H_ecto%E6%A8%A1%E5%9E%8B.md
https://hexdocs.pm/ecto/Ecto.Query.html


上一篇
Laravel起步走:artisan tinker操作ORM練習
下一篇
物件導向與函數導向簡析
系列文
新時代的網頁框架比較-- 淺談Rails、Django、Phoenix、Laravel31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言