diff --git a/lib/helper/utils.ex b/lib/helper/utils.ex index a522a6788..5afd540a8 100644 --- a/lib/helper/utils.ex +++ b/lib/helper/utils.ex @@ -246,4 +246,40 @@ defmodule Helper.Utils do end def str_occurence(_, _), do: "must be strings" + + @spec large_than(String.t() | Integer.t(), Integer.t()) :: true | false + def large_than(value, target) when is_binary(value) and is_integer(target) do + String.length(value) >= target + end + + def large_than(value, target) when is_integer(value) and is_integer(target) do + value >= target + end + + @spec large_than(String.t() | Integer.t(), Integer.t(), :no_equal) :: true | false + def large_than(value, target, :no_equal) when is_binary(value) and is_integer(target) do + String.length(value) > target + end + + def large_than(value, target, :no_equal) when is_integer(value) and is_integer(target) do + value > target + end + + @spec less_than(String.t() | Integer.t(), Integer.t()) :: true | false + def less_than(value, target) when is_binary(value) and is_integer(target) do + String.length(value) <= target + end + + def less_than(value, target) when is_integer(value) and is_integer(target) do + value <= target + end + + @spec less_than(String.t() | Integer.t(), Integer.t(), :no_equal) :: true | false + def less_than(value, target, :no_equal) when is_binary(value) and is_integer(target) do + String.length(value) < target + end + + def less_than(value, target, :no_equal) when is_integer(value) and is_integer(target) do + value < target + end end diff --git a/lib/helper/validator/guards.ex b/lib/helper/validator/guards.ex new file mode 100644 index 000000000..6aa4c8b7a --- /dev/null +++ b/lib/helper/validator/guards.ex @@ -0,0 +1,7 @@ +defmodule Helper.Validator.Guards do + @moduledoc """ + general guards + """ + defguard g_pos_int(value) when is_integer(value) and value >= 0 + defguard g_not_nil(value) when not is_nil(value) +end diff --git a/lib/helper/validator/schema.ex b/lib/helper/validator/schema.ex index 2f847f317..3aabd54a6 100644 --- a/lib/helper/validator/schema.ex +++ b/lib/helper/validator/schema.ex @@ -23,6 +23,13 @@ defmodule Helper.Validator.Schema do data = %{checked: true, label: "done"} Schema.cast(schema, data) """ + + alias Helper.Utils + import Helper.Validator.Guards, only: [g_pos_int: 1, g_not_nil: 1] + + @support_min [:string, :number] + + @spec cast(map, map) :: {:ok, :pass} | {:error, map} def cast(schema, data) do errors_info = cast_errors(schema, data) @@ -62,11 +69,8 @@ defmodule Helper.Validator.Schema do {:ok, value} false -> - {:error, - %{ - field: field, - message: "should be: #{enum |> Enum.join(" | ")}" - }} + msg = %{field: field, message: "should be: #{enum |> Enum.join(" | ")}"} + {:error, msg} end end @@ -78,22 +82,11 @@ defmodule Helper.Validator.Schema do end # custom validate logic - defp match(field, value, :string, [{:min, min} | options]) - when is_binary(value) and is_integer(min) do - case String.length(value) >= min do - true -> - match(field, value, :string, options) - - false -> - error(field, value, :min, min) - end - end - - defp match(field, value, :number, [{:min, min} | options]) - when is_integer(value) and is_integer(min) do - case value >= min do + defp match(field, value, type, [{:min, min} | options]) + when type in @support_min and g_not_nil(value) and g_pos_int(min) do + case Utils.large_than(value, min) do true -> - match(field, value, :number, options) + match(field, value, type, options) false -> error(field, value, :min, min) @@ -109,13 +102,14 @@ defmodule Helper.Validator.Schema do defp match(field, value, :boolean, []) when is_boolean(value), do: done(field, value) # main type end - # judge option + # error for option defp match(field, value, type, [option]) when is_tuple(option) do # 如果这里不判断的话会和下面的 match 冲突,是否有更好的写法? case option_valid?(option) do true -> error(field, value, type) + # unknow option or option not valid false -> {k, v} = option error(field, value, option: "#{to_string(k)}: #{to_string(v)}") diff --git a/test/helper/utils_test.exs b/test/helper/utils_test.exs index ec5e43b94..228690048 100644 --- a/test/helper/utils_test.exs +++ b/test/helper/utils_test.exs @@ -128,4 +128,38 @@ defmodule GroupherServer.Test.Helper.UtilsTest do assert 0 == Utils.str_occurence("hello world", "foo") end end + + describe "[basic compare]" do + test "large_than work for both number and string" do + assert true == Utils.large_than(10, 9) + assert false == Utils.large_than(8, 9) + + assert true == Utils.large_than("lang", 3) + assert false == Utils.large_than("ok", 3) + end + + test "large_than equal case" do + assert true == Utils.large_than(9, 9) + assert false == Utils.large_than(9, 9, :no_equal) + + assert true == Utils.large_than("lang", 4) + assert false == Utils.large_than("lang", 4, :no_equal) + end + + test "less_than work for both number and string" do + assert false == Utils.less_than(10, 9) + assert true == Utils.less_than(8, 9) + + assert false == Utils.less_than("lang", 3) + assert true == Utils.less_than("ok", 3) + end + + test "less_than equal case" do + assert true == Utils.less_than(9, 9) + assert false == Utils.less_than(9, 9, :no_equal) + + assert true == Utils.less_than("lang", 4) + assert false == Utils.less_than("lang", 4, :no_equal) + end + end end diff --git a/test/helper/validator/schema_test.exs b/test/helper/validator/schema_test.exs index fae9c0d71..690204f03 100644 --- a/test/helper/validator/schema_test.exs +++ b/test/helper/validator/schema_test.exs @@ -85,7 +85,6 @@ defmodule GroupherServer.Test.Helper.Validator.Schema do # hello world end - @tag :wip2 test "number with wrong option" do schema = %{"text" => [:number, required: true, min: "5"]} data = %{"text" => 1}