Skip to content
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## v3.0.0-rc.5

### Fixed

- `ROUND` now rounds whole numbers and numeric strings. It used to accept only
floats, so `ROUND(5)`, `ROUND(2 * 3)` and a whole-number variable all raised a
`FunctionClauseError`. A value that is not a number now surfaces as the
standard "expression is not a number" `Expression.Error`, as `FIXED` already
does.

## v3.0.0-rc.4

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ by adding `expression` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:expression, "~> 3.0.0-rc.4"}
{:expression, "~> 3.0.0-rc.5"}
]
end
```
Expand Down
9 changes: 7 additions & 2 deletions lib/expression/callbacks/standard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ defmodule Expression.Callbacks.Standard do
[value] = eval_args!([value], ctx)

value
|> Decimal.from_float()
|> coerce_to_number!()
|> number_to_decimal()
|> Decimal.round(0)
|> Decimal.to_string(:normal)
end
Expand All @@ -361,11 +362,15 @@ defmodule Expression.Callbacks.Standard do
[value, places] = eval_args!([value, places], ctx)

value
|> Decimal.from_float()
|> coerce_to_number!()
|> number_to_decimal()
|> Decimal.round(places)
|> Decimal.to_string(:normal)
end

defp number_to_decimal(number) when is_float(number), do: Decimal.from_float(number)
defp number_to_decimal(number) when is_integer(number), do: Decimal.new(number)

@doc """
MID extracts part of a string, starting at a specified position and for a specified length.

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Expression.MixProject do
use Mix.Project

@version "3.0.0-rc.4"
@version "3.0.0-rc.5"

def project do
[
Expand Down
29 changes: 29 additions & 0 deletions test/expression_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,35 @@ defmodule ExpressionTest do
%Expression.Error{message: "expression is not a number: `\"not a number\"`"}} =
Expression.evaluate_block("fixed(value, 2, true)", %{"value" => "not a number"})
end

test "round/1 rounds a whole number to itself" do
assert {:ok, "4"} == Expression.evaluate_block("round(value)", %{"value" => 4})
end

test "round/2 rounds a whole number to the given places" do
assert {:ok, "4.00"} == Expression.evaluate_block("round(value, 2)", %{"value" => 4})
end

test "round/1 with a numeric string still rounds the number" do
assert {:ok, "4"} == Expression.evaluate_block("round(value)", %{"value" => "3.7"})
end

test "round/1 with a non-numeric value returns an error tuple instead of crashing" do
assert {:error,
%Expression.Error{message: "expression is not a number: `\"not a number\"`"}} =
Expression.evaluate_block("round(value)", %{"value" => "not a number"})
end

test "round/1 with a nil value returns an error tuple instead of crashing" do
assert {:error, %Expression.Error{message: "expression is not a number: `nil`"}} =
Expression.evaluate_block("round(value)", %{"value" => nil})
end

test "round/2 with a non-numeric value returns an error tuple instead of crashing" do
assert {:error,
%Expression.Error{message: "expression is not a number: `\"not a number\"`"}} =
Expression.evaluate_block("round(value, 2)", %{"value" => "not a number"})
end
end

test "escaping" do
Expand Down
Loading