Phoenix email 規(guī)則

2023-12-18 14:24 更新

郵箱的限制有如下三個:

限制 錯誤提示
必填 請?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@bA@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 已被人占用一章,回顧一下。

我們的步驟是這樣的:

  1. 執(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
  2. 打開新建的 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
  3. 接著在命令行下執(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
  4. 最后,將新索引的名稱賦給 unique_constraintname 參數(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ī)則。如果你心里不踏實,可以打開瀏覽器頁面人肉測試一番 - 但建議你不要,要控制住這種無用的欲望。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號