Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Zoey de Souza Pessanha
Zoey de Souza Pessanha

Posted on

     

Parsing and Validating Data in Elixir

In the enchanting world of Elixir programming, data validation is a quest every developer embarks on. It's a journey through the land of schemas, types, and constraints, ensuring data integrity and correctness. Today, we'll explore four powerful artifacts: Ecto, Norm, Drops, and Peri. Each of these tools offers unique powers for taming your data. We'll delve into their strengths, use cases, and compare them to help you choose the right one for your quest.

The Quest: Parse, Don't Validate

Before we embark on our journey, let's discuss a guiding principle in functional programming:Parse, Don't Validate. This pattern emphasizes transforming data into a well-defined structure as early as possible. By doing so, you avoid scattered, ad-hoc validation throughout your codebase, leading to clearer, more maintainable code. It's like casting a spell to organize the chaos of raw data into a neat, structured form.

The Artifacts

1. Ecto

Ecto is a robust toolkit primarily designed for interacting with databases. However, it also offers powerful capabilities for embedded schemas and schemaless changesets, making it versatile for data validation.

Embedded Schemas

Ecto allows defining schemas that don't map to a database table, ideal for validating nested data structures.

defmoduleUserdouseEcto.Schemaembedded_schemadofield:name,:stringfield:email,:stringendenddefchangeset(data)do%User{}|>Ecto.Changeset.cast(data,[:name,:email])|>Ecto.Changeset.validate_required([:name,:email])end
Enter fullscreen modeExit fullscreen mode

Schemaless Changesets

For dynamic data, Ecto provides schemaless changesets, offering flexibility at the cost of increased complexity.

defchangeset(data)doEcto.Changeset.cast({%{},%{name::string,email::string}},data,[:name,:email])|>Ecto.Changeset.validate_required([:name,:email])end
Enter fullscreen modeExit fullscreen mode

2. Norm

Norm focuses on defining and conforming to data structures with custom predicates, offering a clean syntax and powerful validation.

defmoduleUserdoimportNormdefschemadoschema(%{name:spec(is_binary()),age:spec(is_integer()and&(&1>18))})endendNorm.conform(%{name:"Jane",age:25},User.schema())# => {:ok, %{name: "Jane", age: 25}}
Enter fullscreen modeExit fullscreen mode

3. Drops

Drops is a newer library that provides a rich set of tools for defining and validating schemas, leveraging Elixir's type system.

defmoduleUserContractdouseDrops.Contractschemado%{required(:name)=>string(:filled?),required(:age)=>integer(gt?:18)}endendUserContract.conform(%{name:"Jane",age:21})# => {:ok, %{name: "Jane", age: 21}}
Enter fullscreen modeExit fullscreen mode

4. Peri

Peri is inspired by Clojure's Plumatic Schema, focusing on validating raw maps with nested schemas and optional fields. It's designed to be powerful yet simple, embracing the "Parse, Don't Validate" pattern.

defmoduleMySchemasdoimportPeridefschema:user,%{name::string,age::integer,email:{:required,:string},role:{:enum,[:admin,:user]}}defschema:profile,%{user:{:custom,&MySchemas.user/1},bio::string}endMySchemas.user(%{name:"John",age:30,email:"john@example.com",role::admin})# => {:ok, %{name: "John", age: 30, email: "john@example.com", role: :admin}}MySchemas.user(%{name:"John",age:"thirty",email:"john@example.com"})# => {:error, [%Peri.Error{path: [:age], message: "expected integer received \"thirty\""}]}
Enter fullscreen modeExit fullscreen mode

Conditional and Composable Types in Peri

Peri shines with its support for conditional and composable types, making it a powerful tool for complex validation scenarios.

defmoduleAdvancedSchemasdoimportPeridefschema:user,%{name::string,age:{:cond,&(&1>=18),:integer,:nil},email:{:either,{:string,:nil}},preferences:{:list,{:oneof,[:string,:atom]}}}endAdvancedSchemas.user(%{name:"Alice",age:25,email:nil,preferences:["coding",:reading]})# => {:ok, %{name: "Alice", age: 25, email: nil, preferences: ["coding", :reading]}}AdvancedSchemas.user(%{name:"Bob",age:17})# => {:ok, %{name: "Bob", age: 17, email: nil, preferences: nil}}
Enter fullscreen modeExit fullscreen mode

Conclusion

Each of these tools offers unique advantages and caters to different needs:

  • Ecto is great for data associated with databases but can handle schemaless and embedded data structures too.
  • Norm provides a clean and powerful way to define and validate data structures.
  • Drops leverages Elixir's type system and offers rich schema definitions and validations.
  • Peri emphasizes simplicity and power, supporting complex types and conditional validations.

By understanding the strengths and weaknesses of each, you can choose the right tool for your data validation needs in Elixir. Happy coding, fellow sorcerers of Elixiria!

References

Feel free to dive into the source code and contribute to these projects to make Elixiria an even more magical place!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Location
    Campos dos Goytacazes, RJ, Brazil
  • Education
    Computer Science Student
  • Work
    Full Stack Developer at Nubank
  • Joined

More fromZoey de Souza Pessanha

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp