郵箱的限制有如下三個:
限制 | 錯誤提示 |
---|---|
必填 | 請?zhí)顚?/td> |
不能重復(fù) | 郵箱已被人占用 |
郵箱必須包含 @ 字符 |
郵箱格式錯誤 |
因為我們在前幾章的 username
里涉及過這三個規(guī)則,所以這里不再啰嗦分出章節(jié)。
email 必填
首先,添加測試規(guī)則,驗證 email
為空時的錯誤提示:
diff --git a/test/tv_recipe/users_test.exs b/test/tv_recipe/users_test.exs
index f70d4a1..bae1e57 100644
--- a/test/tv_recipe/users_test.exs
+++ b/test/tv_recipe/users_test.exs
@@ -70,4 +70,9 @@ defmodule TvRecipe.UserTest do
assert %{username: ["系統(tǒng)保留,無法注冊,請更換"]} = errors_on(%User{}, %{@valid_attrs | username: "admin"})
assert %{username: ["系統(tǒng)保留,無法注冊,請更換"]} = errors_on(%User{}, %{@valid_attrs | username: "administrator"})
end
+
+ test "email should not be blank" do
+ attrs = %{@valid_attrs | email: ""}
+ assert %{email: ["請?zhí)顚?]} = errors_on(%User{}, attrs)
+ end
end
因為我們前面在處理 username 必填時,也一起處理過 email
,所以這個測試是會通過的。
email 格式
因為郵箱地址的格式花樣太多,所以這里只簡單驗證用戶填寫的郵箱地址中是否包含 @
字符。一般情況下,在用戶注冊成功后,系統(tǒng)會發(fā)送一封確認(rèn)郵件到用戶郵箱,但因為郵件系統(tǒng)涉及第三方服務(wù),所以本教程不做展開。
我們先添加一個測試:
diff --git a/test/tv_recipe/users_test.exs b/test/tv_recipe/users_test.exs
index bae1e57..67aab23 100644
--- a/test/tv_recipe/users_test.exs
+++ b/test/tv_recipe/users_test.exs
@@ -75,4 +75,9 @@ defmodule TvRecipe.UserTest do
attrs = %{@valid_attrs | email: ""}
assert %{email: ["請?zhí)顚?]} = errors_on(%User{}, attrs)
end
+
+ test "email should contain @" do
+ attrs = %{@valid_attrs | email: "ab"}
+ assert %{email: ["郵箱格式錯誤"]} = errors_on(%User{}, attrs)
+ end
end
因為我們的規(guī)則還沒寫,所以測試不會通過。
下面在 user.ex
文件中添加 validate_format
驗證規(guī)則:
diff --git a/lib/tv_recipe/users/user.ex b/lib/tv_recipe/users/user.ex
index 35e4d0b..fef942b 100644
--- a/lib/tv_recipe/users/user.ex
+++ b/lib/tv_recipe/users/user.ex
@@ -21,6 +21,7 @@ defmodule TvRecipe.User do
|> validate_length(:username, max: 15, message: "用戶名最長 15 位")
|> validate_exclusion(:username, ~w(admin administrator), message: "系統(tǒng)保留,無法注冊,請更換")
|> unique_constraint(:username, name: :users_lower_username_index, message: "用戶名已被人占用")
+ |> validate_format(:email, ~r/@/, message: "郵箱格式錯誤")
|> unique_constraint(:email)
end
end
再運(yùn)行測試,悉數(shù)通過。
email 不允許重復(fù)
仍是先寫測試:
diff --git a/test/tv_recipe/users_test.exs b/test/tv_recipe/users_test.exs
index 67aab23..f6c99e5 100644
--- a/test/tv_recipe/users_test.exs
+++ b/test/tv_recipe/users_test.exs
@@ -80,4 +80,16 @@ defmodule TvRecipe.UserTest do
attrs = %{@valid_attrs | email: "ab"}
assert %{email: ["郵箱格式錯誤"]} = errors_on(%User{}, attrs)
end
+
+ test "email should be unique" do
+ # 在測試數(shù)據(jù)庫中插入新用戶
+ user_changeset = User.changeset(%User{}, @valid_attrs)
+ TvRecipe.Repo.insert! user_changeset
+
+ # 嘗試插入同郵箱地址的用戶,應(yīng)報告錯誤
+ assert {:error, changeset} = TvRecipe.Repo.insert(User.changeset(%User{}, %{@valid_attrs | username: "samchen"}))
+
+ # 錯誤信息為“郵箱已被人占用”
+ assert %{email: ["郵箱已被人占用"]} = errors_on(changeset)
+ end
end
然后給 unique_constraint
添加自定義消息。
打開 user.ex
文件,添加 message
如下:
diff --git a/lib/tv_recipe/users/user.ex b/lib/tv_recipe/users/user.ex
index fef942b..54e7e4c 100644
--- a/lib/tv_recipe/users/user.ex
+++ b/lib/tv_recipe/users/user.ex
@@ -22,6 +22,6 @@ defmodule TvRecipe.User do
|> validate_exclusion(:username, ~w(admin administrator), message: "系統(tǒng)保留,無法注冊,請更換")
|> unique_constraint(:username, name: :users_lower_username_index, message: "用戶名已被人占用")
|> validate_format(:email, ~r/@/, message: "郵箱格式錯誤")
- |> unique_constraint(:email)
+ |> unique_constraint(:email, message: "郵箱已被人占用")
end
end
再運(yùn)行測試,就都通過了。
最后,還有一個測試,是關(guān)于 email
大小寫的,即 a@b
與 A@b
應(yīng)當(dāng)認(rèn)為是一致的:
diff --git a/test/tv_recipe/users_test.exs b/test/tv_recipe/users_test.exs
index f6c99e5..82dcf6a 100644
--- a/test/tv_recipe/users_test.exs
+++ b/test/tv_recipe/users_test.exs
@@ -92,4 +92,14 @@ defmodule TvRecipe.UserTest do
# 錯誤信息為“郵箱已被人占用”
assert %{email: ["郵箱已被人占用"]} = errors_on(changeset)
end
+
+ test "email should be case insensitive" do
+ user_changeset = User.changeset(%User{}, @valid_attrs)
+ TvRecipe.Repo.insert! user_changeset
+
+ # 嘗試插入大小寫不一致的郵箱,應(yīng)報告錯誤
+ another_user_changeset = User.changeset(%User{}, %{@valid_attrs | username: "samchen", email: "chenXsan@gmail.com"})
+ assert {:error, changeset} = TvRecipe.Repo.insert(another_user_changeset)
+ assert %{email: ["郵箱已被人占用"]} = errors_on(changeset)
+ end
end
現(xiàn)在,測試是失敗的。
如果你忘了接下來要怎么處理,請先打開 username 已被人占用一章,回顧一下。
我們的步驟是這樣的:
-
執(zhí)行
mix ecto.gen.migration alter_email_index
命令新建一個 migration 文件:$ mix ecto.gen.migration alter_email_index Compiling 2 files (.ex) * creating priv/repo/migrations * creating priv/repo/migrations/20170124142809_alter_email_index.exs
-
打開新建的
20170124142809_alter_email_index.exs
文件,做如下修改:diff --git a/priv/repo/migrations/20170124142809_alter_email_index.exs b/priv/repo/migrations/20170124142809_alter_email_index.exs index 313bda6..746a00d 100644 --- a/priv/repo/migrations/20170124142809_alter_email_index.exs +++ b/priv/repo/migrations/20170124142809_alter_email_index.exs @@ -2,6 +2,7 @@ defmodule TvRecipe.Repo.Migrations.AlterEmailIndex do use Ecto.Migration def change do - + drop index(:users, [:email]) # 移除舊索引 + create unique_index(:users, ["lower(email)"]) # 增加新索引 end end
-
接著在命令行下執(zhí)行
mix ecto.migrate
命令:$ mix ecto.migrate 22:30:46.531 [info] == Running TvRecipe.Repo.Migrations.AlterEmailIndex.change/0 forward 22:30:46.531 [info] drop index users_email_index 22:30:46.532 [info] create index users_lower_email_index 22:30:46.568 [info] == Migrated in 0.0s
-
最后,將新索引的名稱賦給
unique_constraint
的name
參數(shù):diff --git a/lib/tv_recipe/users/user.ex b/lib/tv_recipe/users/user.ex index 54e7e4c..9307a3c 100644 --- a/lib/tv_recipe/users/user.ex +++ b/lib/tv_recipe/users/user.ex @@ -22,6 +22,6 @@ defmodule TvRecipe.User do |> validate_exclusion(:username, ~w(admin administrator), message: "系統(tǒng)保留,無法注冊,請更換") |> unique_constraint(:username, name: :users_lower_username_index, message: "用戶名已被人占用") |> validate_format(:email, ~r/@/, message: "郵箱格式錯誤") - |> unique_constraint(:email, message: "郵箱已被人占用") + |> unique_constraint(:email, name: :users_lower_email_index, message: "郵箱已被人占用") end end
再跑一遍測試:
$ mix test test/tv_recipe/users_test.exs
..............
Finished in 0.2 seconds
14 tests, 0 failures
通過了。這樣,我們就搞定了 email
所有規(guī)則。如果你心里不踏實,可以打開瀏覽器頁面人肉測試一番 - 但建議你不要,要控制住這種無用的欲望。
更多建議: