Reputation: 2731
I am struggling to come up with a clean way to do input validation in Elixir.
In a OOP language i would do something like this:
def my_func(a, b):
if !validate_a(a):
raise ArgumentError
if !validate_b(b):
raise ArgumentError
return "something"
The best i could come up with in Elixir is this:
def my_func(a, b) do
cond do
not valid_a?(a) -> {:error, "a is invalid"}
not valid_b?(b) -> {:error, "b is invalid"}
:otherwise -> {:ok, "something"}
end
end
I know that i could also raise an exception in Elxir, but i like pattern-matching against the return type a lot better, since my code doesn't get cluttered with try/rescue blocks.
Is there a preferred pattern to do this in Elixir?
Upvotes: 0
Views: 2939
Reputation: 10041
Depending on the complexity of your validations and what your data looks like, you could also opt to use Ecto.Changeset
even if you do not plan to store the data.
Something really simple like the following
defmodule Foo do
use Ecto.Schema
import Ecto.Changeset
schema "my_schema" do
field :name, :string
field :age, :integer
end
def changeset(struct, params) do
struct
|> cast(params, [:name, :age])
|> validate_required([:name, :age])
|> validate_number(:age, greater_than: 18)
end
end
Once you run the changeset/2
function, you will be given an Ecto.Changeset
as a result which has a valid?
field. If this is true, it passed all of your validations. If it is false, it will also tell you why from the :errors
key from the changeset.
Upvotes: 3
Reputation: 5812
Everything depends what comes after the validation and what kind of validation you want to have.
For example: if you simply validate is a
and b
are integers you can use guard
clauses in definitions of the functions.
def my_func(a, b) when is_integer(a) and is_integer(b) do
# your code - validation passed
end
def my_func(_, _) do
# validation failed
end
In terms of custom validation is good to have separate function and you can use it in your "main" function - your code is cleaner and easier to test, since it's better isolated. In your case - this cond
with validation might be in different function.
When dealing with validation in Phoenix controllers you can obviously create own Plugs, which is really handy when you can use like before
in Ruby on Rails controllers.
Upvotes: 4