Phoenix username 必填

2023-12-18 14:12 更新

上一章里,我們用 mix phx.gen.html 命令創(chuàng)建出完整用戶界面,并且具備增加、刪除、更改、查詢用戶的功能。

這一章,我們將實現(xiàn) username 的第一個規(guī)則:username 必填,如果未填寫,提示用戶請?zhí)顚?/code>。

先來看看,在 http://localhost:4000/users/new 頁面上,提交空白用戶名的話,我們會看到什么?

頁面會提示我們,can't be blank。

很好,雖然不知道怎么回事,但必填的限制已經(jīng)有了,那如何將它改成請?zhí)顚?/code>呢?

打開 web/models/user.ex 文件,其中有一行:

|> validate_required([:username, :email, :password])

正是 validate_required 明確了 username 為必填。從文檔里我們看到,validate_required 還接收一個可選的 message 參數(shù),用于自定義錯誤消息。

讓我們加上試試:

diff --git a/tv_recipe/users/user.ex b/tv_recipe/users/user.ex
index b7713a0..87ce321 100644
--- a/web/models/user.ex
+++ b/web/models/user.ex
@@ -15,7 +15,7 @@ defmodule TvRecipe.User do
   def changeset(struct, params \\ %{}) do
     struct
     |> cast(params, [:username, :email, :password])
-    |> validate_required([:username, :email, :password])
+    |> validate_required([:username, :email, :password], message: "請?zhí)顚?)
     |> unique_constraint(:username)
     |> unique_constraint(:email)
   end

打開網(wǎng)址,提交空白用戶名,頁面上已經(jīng)顯示“請?zhí)顚憽绷耍?/p>

show error when user submit blank username

很好,但請注意,我們這是人肉測試。

又或者,我們可以用 Phoenix 生成的測試文件來驗證。

打開 test/tv_recipe/users_test.exs 文件,默認內容如下:

defmodule TvRecipe.UserTest do
  use TvRecipe.ModelCase

  alias TvRecipe.User

  @valid_attrs %{email: "some content", password: "some content", username: "some content"}
  @invalid_attrs %{}

  test "changeset with valid attributes" do
    changeset = User.changeset(%User{}, @valid_attrs)
    assert changeset.valid?
  end

  test "changeset with invalid attributes" do
    changeset = User.changeset(%User{}, @invalid_attrs)
    refute changeset.valid?
  end
end

文件中有兩個變量,@valid_attrs 表示有效的 User 屬性,@invalid_attrs 表示無效的 User 屬性,我們按本章開頭擬定的規(guī)則修改 @valid_attrs

diff --git a/test/tv_recipe/users_test.exs b/test/tv_recipe/users_test.exs
index 1d5494f..7c73207 100644
--- a/test/tv_recipe/users_test.exs
+++ b/test/tv_recipe/users_test.exs
@@ -3,7 +3,7 @@ defmodule TvRecipe.UserTest do

   alias TvRecipe.User

-  @valid_attrs %{email: "some content", password: "some content", username: "some content"}
+  @valid_attrs %{email: "chenxsan@gmail.com", password: "some content", username: "chenxsan"}
   @invalid_attrs %{}

   test "changeset with valid attributes" do

接著,在 users_test.exs 文件中添加一個新測試:

diff --git a/test/models/user_test.exs b/test/models/user_test.exs
index 7c73207..4c174ab 100644
--- a/test/tv_recipe/users_test.exs
+++ b/test/tv_recipe/users_test.exs
@@ -15,4 +15,9 @@ defmodule TvRecipe.UserTest do
     changeset = User.changeset(%User{}, @invalid_attrs)
     refute changeset.valid?
   end
+
+  test "username should not be blank" do
+    attrs = %{@valid_attrs | username: ""}
+    assert %{username: ["請?zhí)顚?] } = errors_on(%User{}, attrs)
+  end
 end

這里,%{@valid_attrs | username: ""} 是 Elixir 更新映射(Map)的一個方法。

至于 errors_on/2 函數(shù),它需要新增在 test/support/data_case.ex 文件中:

   def errors_on(changeset) do
     Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
       Regex.replace(~r"%{(\w+)}", message, fn _, key ->
         opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
       end)
     end)
   end
+
+  def errors_on(struct, attrs) do
+    changeset = struct.__struct__.changeset(struct, attrs)
+    errors_on(changeset)
+  end
end

是否很吃驚?要知道,如果是在 JavaScript 里寫兩個同名函數(shù),后一個函數(shù)會覆蓋前一個的定義,而 Elixir 下,我們可以定義多個同名函數(shù),它們能處理不同的狀況,而又互不干擾。

它檢查給定數(shù)據(jù)中的錯誤消息,并返回給我們。

現(xiàn)在在命令行下運行:

$ mix test test/tv_recipe/users_test.exs

結果如下:

...

Finished in 0.07 seconds
3 tests, 0 failures

測試通過?,F(xiàn)在我們可以放心地認為,用戶提交空白 username 時,Phoenix 一定會返回“請?zhí)顚憽钡腻e誤消息。

為什么要寫測試?

可能很多人都抱有這個疑問。測試增加了我們的工作量,而它的作用又不那么明顯。更何況,這還只是一個入門教程。

我想談幾點個人感受:

  1. 我不喜歡拿自己當人肉測試機。
  2. 代碼的修改是必然發(fā)生的,而我們在修改時無法保證周全,此時測試即任務清單,它幫我們指出,哪些地方的代碼需統(tǒng)一修改,這樣我們才能保證代碼的質量。
  3. 在團隊協(xié)作中,你很難保證別人的代碼不會破壞到自己的那部分。比如一個開源項目,有人在 github 上提了 pull request,你如果有測試代碼,馬上就能知道,這個 pull request 是否會破壞其它功能,如果你沒有測試代碼,好了,你得一行一行驗證了 - 這種成本無論是對維護者還是貢獻者來說,都是極大的浪費。

而況在 Phoenix 框架下,測試非常容易寫。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號