ProductPromotion
Logo

Elixir

made by https://0x3d.site

GitHub - bobfp/skooma: Elixir data validation library
Elixir data validation library. Contribute to bobfp/skooma development by creating an account on GitHub.
Visit Site

GitHub - bobfp/skooma: Elixir data validation library

GitHub - bobfp/skooma: Elixir data validation library

Skooma

Hex.pm Build Status

Simple data validation library for elixir.

Skooma was developed to be used to describe and validate the incoming and outgoing data structures from a REST API, but it can easily be used throughout a code base. No one likes writing data schemas, so the main focus during development was to develop an API that allowed for quick and simple schema creation.

Table of Contents

Installation

The package can be installed by adding skooma to your list of dependencies in mix.exs:

def deps do
  [
    {:skooma, "~> 0.2.0"}
  ]
end

Overview

Skooma exposes the function valid?/2

data = %{
  :race => "Khajiit",
  :name => "Bob",
  :level => 6,
  "potions" => ["Skooma", "Fortify Health", "Fortify Magicka"]
  
}
schema = %{
  :race => :string,
  :name => :string,
  :level => :int,
  :gender => [:atom, :not_required]
  "potions" => [:list, :string],
}
Skooma.valid?(data, schema)
# :ok

Basics

Skooma supports all of the elixir data types:

Boolean

data = false
schema = :bool
Skooma.valid?(data, schema) #:ok

String

data = "test"
schema = :string
Skooma.valid?(data, schema) #:ok

Integer

data = 7
schema = :int
Skooma.valid?(data, schema) #:ok

Float

data = 3.14
schema = :float
Skooma.valid?(data, schema) #:ok

Number

data = 1.41
schema = :number
Skooma.valid?(data, schema) #:ok

Atom

data = :thing
schema = :atom
Skooma.valid?(data, schema) #:ok

Map

data = %{
  :race => "Khajiit",
  "level" => 6,
}
schema = %{
  :race => :string,
  "level" => :int,
}
Skooma.valid?(data, schema) # :ok

List

data = [1, 2, 3]
schema = [:list, :int]
Skooma.valid?(data, schema) # :ok

Tuple

data = {456.89, 365.65}
schema = {:float, :float}
Skooma.valid?(data, schema) # :ok

Keyword List

data = [key1: "value1", key2: 2, key3: :atom3]
schema = [key1: :string, key2: :int, key3: :atom]
Skooma.valid?(data, schema) # :ok

Complex Schemas

Not Required

Sometimes, you want a field to be optional. In this case, use the :not_required atom.

data = %{"key2" => 3}
schema = %{:key1 => [:string, :not_required], "key2" => :int}
Skooma.valid?(data, schema) # :ok

A nil value will also pass if :not_required is invoked

data = %{:key1 => nil, "key2" => 3}
schema = %{:key1 => [:string, :not_required], "key2" => :int}
Skooma.valid?(data, schema) # :ok

Complex Maps

Skooma schemas can be nested and combined to match any data strucutre.

my_hero = %{
  race: "Khajiit",
  stats: %{
    hp: 100,
    magicka: 60,
    xp: 5600
  }
}
schema = %{
  race: :string,
  stats: %{
    hp: :int,
    magicka: :int,
    xp: :int
  }
}
Skooma.valid?(my_hero, schema) # :ok

For flexibilty and incase of recursive data structures, functions that return maps can also be used. In this case, the :map type must be explicitly used

my_hero = %{
  name: "Alkosh"
  race: "Khajiit",
  friends: [ 
    %{name: "Asurah", race: "Khajiit"}, 
    %{name: "Carlos", race: "Dwarf"}
  ]
}

def hero_schema() do
  %{
    name: :string,
    race: :string,
    friends: [:list, :map, :not_required, &hero_schema/0]
   }
end
Skooma.valid?(my_hero, hero_schema) # :ok

Union Types

Skooma also lets you supply a list of schemas to allow for flexible data structures

data1 = %{key1: "value1"}
data2 = 8

schema = [:union, [%{key1: :string}, :int]]

Skooma.valid?(data1, schema) # :ok
Skooma.valid?(data2, schema) # :ok

Error Handling

If a the data and schema passed to valid?/2 match, an :ok will be returned.

If a match isn't made, valid?/2 returns something of the form {:error, ["Error Mesasge 1", "Error Message 2"...])

A few examples are:

data = 7
schema = [:string]
Skooma.valid?(data, schema) # {:error, ["Expected STRING, got INTEGER 7"]}
data = %{
  :key1 => "value1",
  "key2" => %{color: "blue"},
  "things" => ["thing1", 5],
  "stuff" => %{key3: %{key4: 9}}
}
schema = %{
  :key1 => [:string],
  "key2" => [:map, %{color: [:string]}],
  "things" => [:list, :string],
  "stuff" => %{key3: %{key4: [:string]}}
}
Skooma.valid?(data, schema) # => 
# {:error, [
#  "Expected STRING, got INTEGER 9, at stuff -> key3 -> key4",
#  "Expected STRING, got INTEGER 5, at things -> index 1"
# ]}

Validators

Skooma comes with a few additional functions that can be used to perform more complex validation.

data = "abc"
schema = [:string, Validators.min_length(4)]
Skooma.valid?(data, schema) # {:error, ["String must be longer than 4 characters"]}

Multiple validators can also be used at the same time:

data = "duck"
schema = [:string, Validators.regex(~r/foo/), Validators.max_length(5)]
Skooma.valid?(data, schema) # {:error, ["String does not match the regex pattern: ~r/foo/"]}

Custom Validators

There is nothing special about the validator functions that Skooma comes with. Making your own is super easy.

There are two types of custom validators. The most barebones is any function that accepts one argument and returns a boolean:

data = 8
schema = [:int, &(&1 == 0)]
Skooma.valid?(data, schema) # {:error, ["Value does not match custom validator"]}

However, if you need more flexibility or a custom error message, instead of returning a boolean, your function should return either :ok or {:error, "Your Custom Error Message"}. Take the built it max_length validator as an example:

def max_length(max) do
    fn (data) ->
      bool = String.length(data) <= max
      if bool do
        :ok
      else
        {:error, "String must be shorter than #{max} characters"}
      end
    end
end

data = "abcdefghijk"
schema = [:string, Validators.max_length(7)]
Skooma.valid?(data, schema) # {:error, ["String must be shorter than 7 characters"]}

Contributions

All contributions are welcome. If there is a validator you would like to see added to the library, please create an issue!

License

MIT © bcoop713

Articles
to learn more about the elixir concepts.

Resources
which are currently available to browse on.

mail [email protected] to add your project or resources here 🔥.

FAQ's
to know more about the topic.

mail [email protected] to add your project or resources here 🔥.

Queries
or most google FAQ's about Elixir.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory