11# username 必填
22
3- [ 上一章] ( /04-user-register/00-prepare.md ) 里,我们用 ` mix phoenix .gen.html ` 命令创建出完整用户界面,并且具备增加、删除、更改、查询用户的功能。
3+ [ 上一章] ( /04-user-register/00-prepare.md ) 里,我们用 ` mix phx .gen.html ` 命令创建出完整用户界面,并且具备增加、删除、更改、查询用户的功能。
44
55这一章,我们将实现 ` username ` 的第一个规则:` username ` 必填,如果未填写,提示用户` 请填写 ` 。
66
2020让我们加上试试:
2121
2222``` elixir
23- diff -- git a/ web / models / user.ex b/ web / models / user.ex
23+ diff -- git a/ tv_recipe / users / user.ex b/ tv_recipe / users / user.ex
2424index b7713a0.. 87ce321 100644
2525-- - a/ web/ models/ user.ex
2626++ + b/ web/ models/ user.ex
@@ -43,7 +43,7 @@ index b7713a0..87ce321 100644
4343
4444又或者,我们可以用 Phoenix 生成的测试文件来验证。
4545
46- 打开 ` test/models/user_test .exs ` 文件,默认内容如下:
46+ 打开 ` test/tv_recipe/users_test .exs ` 文件,默认内容如下:
4747
4848``` elixir
4949defmodule TvRecipe .UserTest do
6868文件中有两个变量,` @valid_attrs ` 表示有效的 ` User ` 属性,` @invalid_attrs ` 表示无效的 ` User ` 属性,我们按本章开头拟定的规则修改 ` @valid_attrs ` :
6969
7070``` elixir
71- diff -- git a/ test/ models / user_test .exs b/ test/ models / user_test .exs
71+ diff -- git a/ test/ tv_recipe / users_test .exs b/ test/ tv_recipe / users_test .exs
7272index 1d5494f.. 7c73207 100644
73- -- - a/ test/ models / user_test .exs
74- ++ + b/ test/ models / user_test .exs
73+ -- - a/ test/ tv_recipe / users_test .exs
74+ ++ + b/ test/ tv_recipe / users_test .exs
7575@@ - 3 ,7 + 3 ,7 @@ defmodule TvRecipe .UserTest do
7676
7777 alias TvRecipe .User
@@ -83,42 +83,53 @@ index 1d5494f..7c73207 100644
8383 test " changeset with valid attributes" do
8484```
8585
86- 接着,在 ` user_test .exs` 文件中添加一个新测试:
86+ 接着,在 ` users_test .exs` 文件中添加一个新测试:
8787
8888``` elixir
8989diff -- git a/ test/ models/ user_test.exs b/ test/ models/ user_test.exs
9090index 7c73207.. 4c174ab 100644
91- -- - a/ test/ models / user_test .exs
92- ++ + b/ test/ models / user_test .exs
91+ -- - a/ test/ tv_recipe / users_test .exs
92+ ++ + b/ test/ tv_recipe / users_test .exs
9393@@ - 15 ,4 + 15 ,9 @@ defmodule TvRecipe .UserTest do
9494 changeset = User .changeset (%User {}, @invalid_attrs )
9595 refute changeset.valid?
9696 end
9797+
9898+ test " username should not be blank" do
9999+ attrs = %{@valid_attrs | username: " " }
100- + assert { : username, " 请填写" } in errors_on (%User {}, attrs)
100+ + assert %{ username: [ " 请填写" ] } = errors_on (%User {}, attrs)
101101+ end
102102 end
103103```
104104
105105这里,` %{@valid_attrs | username: ""} ` 是 Elixir 更新映射(Map)的一个方法。
106106
107- 至于 ` errors_on ` 函数,它定义在 ` tv_recipe/ test/support/model_case .ex` 文件中:
107+ 至于 ` errors_on/2 ` 函数,它需要新增在 ` test/support/data_case .ex ` 文件中:
108108
109109``` elixir
110- def errors_on (struct, data) do
111- struct.__struct__.changeset (struct, data)
112- |> Ecto .Changeset .traverse_errors (& TvRecipe .ErrorHelpers .translate_error / 1 )
113- |> Enum .flat_map (fn {key, errors} -> for msg <- errors, do: {key, msg} end )
110+ def errors_on (changeset) do
111+ Ecto .Changeset .traverse_errors (changeset, fn {message, opts} ->
112+ Regex .replace (~r" %{(\w +)}" , message, fn _ , key ->
113+ opts |> Keyword .get (String .to_existing_atom (key), key) |> to_string ()
114+ end )
115+ end )
116+ end
117+ +
118+ + def errors_on (struct, attrs) do
119+ + changeset = struct.__struct__.changeset (struct, attrs)
120+ + errors_on (changeset)
121+ + end
114122end
115123```
124+
125+ 是否很吃惊?要知道,如果是在 JavaScript 里写两个同名函数,后一个函数会覆盖前一个的定义,而 Elixir 下,我们可以定义多个同名函数,它们能处理不同的状况,而又互不干扰。
126+
116127它检查给定数据中的错误消息,并返回给我们。
117128
118129现在在命令行下运行:
119130
120131``` bash
121- $ mix test test/models/user_test .exs
132+ $ mix test test/tv_recipe/users_test .exs
122133```
123134结果如下:
124135
0 commit comments