Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Decimal validations #3

Merged
merged 4 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions lib/valdi.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Valdi do
- validate string format/pattern
- validate custom function
- validate required (not nil) or not
- validate decimal

Each of these validations can be used separatedly

Expand All @@ -28,6 +29,7 @@ defmodule Valdi do
{:error, "does not match format"}
```
"""
require Decimal

@type error :: {:error, String.t()}

Expand Down Expand Up @@ -159,6 +161,8 @@ defmodule Valdi do
defp get_validator(:in), do: &validate_inclusion/2
defp get_validator(:not_in), do: &validate_exclusion/2
defp get_validator(:each), do: &validate_each_item/2
defp get_validator(:decimal), do: &validate_decimal/2

defp get_validator(name), do: {:error, "validate_#{name} is not support"}

@doc """
Expand Down Expand Up @@ -218,6 +222,7 @@ defmodule Valdi do
def validate_type(value, :atom) when is_atom(value), do: :ok
def validate_type(value, :function) when is_function(value), do: :ok
def validate_type(value, :map) when is_map(value), do: :ok
def validate_type(%Decimal{} = _value, :decimal), do: :ok
def validate_type(_value, :any), do: :ok

def validate_type(value, {:array, type}) when is_list(value) do
Expand Down Expand Up @@ -476,4 +481,76 @@ defmodule Valdi do
{:error, "each validation only support array type"}
end
end

@spec validate_decimal(Decimal.t(), keyword()) :: :ok | error()
def validate_decimal(value, checks) when is_list(checks) do
if Decimal.is_decimal(value) do
Enum.reduce(checks, :ok, fn
check, :ok ->
validate_decimal(value, check)
_, error ->
error
end)
else
{:error, "must be a Decimal.t() type"}
end
end


def validate_decimal(decimal, {:equal_to, %Decimal{} = check_value}) do
if Decimal.eq?(decimal, check_value) do
:ok
else
{:error, "must be equal to #{check_value}"}
end
end

def validate_decimal(decimal, {:greater_than, %Decimal{} = check_value}) do
if Decimal.gt?(decimal, check_value) do
:ok
else
{:error, "must be greater than #{check_value}"}
end
end

def validate_decimal(decimal, {:greater_than_or_equal_to, %Decimal{} = check_value}) do
if Decimal.gt?(decimal, check_value) or Decimal.eq?(decimal, check_value) do
:ok
else
{:error, "must be greater than or equal to #{check_value}"}
end
end

def validate_decimal(decimal, {:min, check_value}) do
validate_decimal(decimal, {:greater_than_or_equal_to, check_value})
end

def validate_decimal(decimal, {:less_than, %Decimal{} = check_value}) do
if Decimal.lt?(decimal, check_value) do
:ok
else
{:error, "must be lesser than #{check_value}"}
end
end

def validate_decimal(decimal, {:less_than_or_equal_to, %Decimal{} = check_value}) do
if Decimal.lt?(decimal, check_value) or Decimal.eq?(decimal, check_value) do
:ok
else
{:error, "must be lesser than or equal to #{check_value}"}
end
end

def validate_decimal(decimal, {:max, %Decimal{} = check_value}) do
validate_decimal(decimal, {:less_than_or_equal_to, check_value})
end

def validate_decimal(_decimal, {check, %Decimal{} = _check_value}) do
{:error, "unknown check '#{check}'"}
end

def validate_decimal(_decimal, {_check, check_value}) do
{:error, "#{check_value} must be a Decimal.t() type"}
end

end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ defmodule Valdi.MixProject do
defp deps do
[
{:ex_doc, "~> 0.24", only: :dev, runtime: false},
{:excoveralls, "~> 0.14", only: :test}
{:excoveralls, "~> 0.14", only: :test},
{:decimal, "~> 2.0"}
]
end
end
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
%{
"certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"},
"ex_doc": {:hex, :ex_doc, "0.25.0", "4070a254664ee5495c2f7cce87c2f43064a8752f7976f2de4937b65871b05223", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2d90883bd4f3d826af0bde7fea733a4c20adba1c79158e2330f7465821c8949b"},
"excoveralls": {:hex, :excoveralls, "0.14.2", "f9f5fd0004d7bbeaa28ea9606251bb643c313c3d60710bad1f5809c845b748f0", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ca6fd358621cb4d29311b29d4732c4d47dac70e622850979bc54ed9a3e50f3e1"},
Expand Down
41 changes: 40 additions & 1 deletion test/valdi_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ defmodule ValdiTest do
[User, %{}, :error],
[{:array, User}, [%User{email: ""}], :ok],
[{:array, User}, [], :ok],
[{:array, User}, %{}, :error]
[{:array, User}, %{}, :error],
[:decimal, Decimal.new("1.0"), :ok],
[:decimal, "1.0", :error],
[:decimal, 1.0, :error]
]

test "validate type" do
Expand Down Expand Up @@ -252,4 +255,40 @@ defmodule ValdiTest do
test "validate each for list data success" do
assert :ok = Valdi.validate([8, 10, 9], type: {:array, :number}, each: [number: [max: 11]])
end

@decimal_tests [
[:equal_to, Decimal.new("10.0"), Decimal.new("10.0"), :ok],
[:equal_to, Decimal.new("10.0"), Decimal.new("11.0"), :error],
[:greater_than_or_equal_to, Decimal.new("10.0"), Decimal.new("10.0"), :ok],
[:greater_than_or_equal_to, Decimal.new("10.0"), Decimal.new("11.0"), :ok],
[:greater_than_or_equal_to, Decimal.new("10.0"), Decimal.new("9.0"), :error],
[:min, Decimal.new("10.0"), Decimal.new("10.0"), :ok],
[:min, Decimal.new("10.0"), Decimal.new("11.0"), :ok],
[:min, Decimal.new("10.0"), Decimal.new("0.0"), :error],
[:greater_than, Decimal.new("10.0"), Decimal.new("11.0"), :ok],
[:greater_than, Decimal.new("10.0"), Decimal.new("10.0"), :error],
[:greater_than, Decimal.new("10.0"), Decimal.new("9.0"), :error],
[:less_than, Decimal.new("10.0"), Decimal.new("9.0"), :ok],
[:less_than, Decimal.new("10.0"), Decimal.new("10.0"), :error],
[:less_than, Decimal.new("10.0"), Decimal.new("11.0"), :error],
[:less_than_or_equal_to, Decimal.new("10.0"), Decimal.new("9.0"), :ok],
[:less_than_or_equal_to, Decimal.new("10.0"), Decimal.new("10.0"), :ok],
[:less_than_or_equal_to, Decimal.new("10.0"), Decimal.new("11.0"), :error],
[:max, Decimal.new("10.0"), Decimal.new("9.0"), :ok],
[:max, Decimal.new("10.0"), Decimal.new("10.0"), :ok],
[:max, Decimal.new("10.0"), Decimal.new("11.0"), :error],
[:unknown_check, Decimal.new("10.0"), Decimal.new("11.0"), :error],
[:min, 11, Decimal.new("11.0"), :error],
]
test "validate decimal" do
for [condition, value, actual_value, expect] <- @decimal_tests do
rs = Valdi.validate(actual_value, type: :decimal, decimal: [{condition, value}])

if expect == :ok do
assert :ok = rs
else
assert {:error, _} = rs
end
end
end
end
Loading