All Projects → vic → Params

vic / Params

Licence: apache-2.0
Easy parameters validation/casting with Ecto.Schema, akin to Rails' strong parameters.

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to Params

Formex
A better form library for Phoenix
Stars: ✭ 206 (-13.81%)
Mutual labels:  ecto, phoenix
Query
Query adds tools to aid the use of Ecto in web settings.
Stars: ✭ 23 (-90.38%)
Mutual labels:  ecto, phoenix
Machinery
State machine thin layer for structs (+ GUI for Phoenix apps)
Stars: ✭ 367 (+53.56%)
Mutual labels:  ecto, phoenix
pretty print formatter
Pretty Print Formatter for Elixir Logger module -- Colorize Ecto's SQL ouput 🖌️
Stars: ✭ 22 (-90.79%)
Mutual labels:  phoenix, ecto
Filterable
Filtering from incoming params in Elixir/Ecto/Phoenix with easy to use DSL.
Stars: ✭ 83 (-65.27%)
Mutual labels:  ecto, phoenix
ecto generator
Generate Ecto schemas from existing database in Phoenix - Elixir
Stars: ✭ 20 (-91.63%)
Mutual labels:  phoenix, ecto
Kaffy
Powerfully simple admin package for phoenix applications
Stars: ✭ 617 (+158.16%)
Mutual labels:  ecto, phoenix
contextual
🌈 Generate your Ecto contexts using this macro and eliminate boilerplate
Stars: ✭ 18 (-92.47%)
Mutual labels:  phoenix, ecto
Polymorphic embed
Polymorphic embeds in Ecto
Stars: ✭ 80 (-66.53%)
Mutual labels:  ecto, phoenix
Ecto morph
morph your Ecto capabilities into the s t r a t o s p h e r e !
Stars: ✭ 72 (-69.87%)
Mutual labels:  ecto, phoenix
ex sieve
Implement dynamic filtering and sorting API for Ecto queries
Stars: ✭ 37 (-84.52%)
Mutual labels:  phoenix, ecto
Mipha
Proj Elixir Forum build with phoenix 1.5.
Stars: ✭ 153 (-35.98%)
Mutual labels:  ecto, phoenix
guardian trackable
A Guardian hook to track user sign ins.
Stars: ✭ 25 (-89.54%)
Mutual labels:  phoenix, ecto
one plus n detector
Elixir library to help you detect 1+n queries in applications using Ecto
Stars: ✭ 20 (-91.63%)
Mutual labels:  phoenix, ecto
ecto nested changeset
Helpers for manipulating nested Ecto changesets
Stars: ✭ 23 (-90.38%)
Mutual labels:  phoenix, ecto
Paper trail
Track and record all the changes in your database with Ecto. Revert back to anytime in history.
Stars: ✭ 380 (+59%)
Mutual labels:  ecto, phoenix
querie
Compose Ecto query from the client side
Stars: ✭ 20 (-91.63%)
Mutual labels:  phoenix, ecto
ecto profiler
Project for Ecto DB profiling
Stars: ✭ 16 (-93.31%)
Mutual labels:  phoenix, ecto
Wallaby
Concurrent browser tests with elixir
Stars: ✭ 1,143 (+378.24%)
Mutual labels:  ecto, phoenix
Phoenix live dashboard
Realtime dashboard with metrics, request logging, plus storage, OS and VM insights
Stars: ✭ 1,657 (+593.31%)
Mutual labels:  ecto, phoenix

Params

Easily define parameter structure and validate/cast with Ecto.Schema

Hex.pm Build Status help maintain this lib

Installation

Available in Hex, the package can be installed as:

  1. Add params to your list of dependencies in mix.exs:
def deps do
  [{:params, "~> 2.0"}]
end

About

If you've been doing Ecto based applications lately, you know Ecto provides a very easy way to populate structs with data coming from request parameters, validating and casting their values along the way.

All this thanks to the Ecto.Schema and Ecto.Changeset modules. The first specifies the fields your model has (typically the same as your db table) and the later provides an easy way to convert potentially unsafe data and validate stuff via changesets.

So for example, in a typical Phoenix application, a User model would look like:

defmodule MyApp.User do
   use MyApp.Web, :model

   schema "users" do
     field :name, :string
     field :age,  :integer
   end

   @required [:name]
   @optional [:age]

   def changeset(changeset_or_model, params) do
     cast(changeset_or_model, params, @required ++ @optional)
     |> validate_required(@required)
   end
end

Normally, changesets are related to some data that will be persisted into a database, and your controller would use the User.changeset method like:

# UserController.ex
def create(conn, params) do
  ch = User.changeset(%User{}, params)
  if ch.valid? do
    ...
end

However, you can use Ecto.Schema for validating/casting data that wont necessarily be persisted into a database. All you need is just specify a module and define your schema, Ecto.Changeset will be happy to work with it.

This comes handy when you have certain parameter structure you want to enforce for example when creating a REST API.

Some Rails developers might be right now wondering where their strong parameters can be defined. On Elixir land, there's no need for such a thing, as we will see, just using an Ecto.Schema with Ecto.Changeset can be much more flexible. Using schemas allows not only specifing which fields we want, but changesets let use type cast, perform validations on values, etc.

So, for example, suppose your Phoenix based API performs a search for kittens looking for a home and expects something like:

{
  "breed": "Russian Blue",
  "age_min": 0,
  "age_max": 5,
  "near_location": {
     "latitude": 92.1,
     "longitude": -82.1
  }
}

You'd like to validate that your controller has received the correct params structure, all you need to do is create a couple of modules:

defmodule MyApi.Params.Location
  use Ecto.Schema
  import Ecto.Changeset

  @required ~w(latitude longitude)
  @optional ~w()

  schema "location params" do
    field :latitude, :float
    field :longitude, :float
  end

  def changeset(ch, params) do
    cast(ch, params, @required ++ @optional)
    |> validate_required(@required)
  end
end

defmodule MyAPI.Params.KittenSearch
  use Ecto.Schema
  import Ecto.Changeset

  @required ~w(breed)
  @optional ~w(age_min age_max)

  schema "params for kitten search" do
    field :breed, :string
    field :age_min, :integer
    field :age_max, :integer
    embeds_one :near_location, Location
  end

  def changeset(ch, params) do
    cast(ch, params, @required ++ @optional)
    |> validate_required(@required)
    |> cast_embed(:near_location, required: true)
  end
end

# On your controller:
def search(conn, params) do
  alias MyAPI.Params.KittenSearch
  changeset = KittenSearch.changeset(%KittenSearch{}, params)
  if changeset.valid? do
    ...
end

That would allow you to take only valid params as you'd normally have with any other Ecto.Schema module.

However it's still a lot of code, most of it defining the the changeset, specifying the optional and required fields, etc.

Params is just a simple Ecto.Schema wrapper for reducing all this boilerplate, while still leting you create custom changesets for parameter processing.

Usage

The previous example could be written like:

defmodule MyAPI.KittenController do

  use Params

  defparams kitten_search %{
    breed!: :string,
    age_max: :integer,
    age_min: [field: :integer, default: 1],
    near_location!: %{
      latitude!: :float, longitude!: :float
    },
    tags: [:string]
  }

  def index(conn, params) do
    changeset = kitten_search(params)
    if changeset.valid? do
      search = Params.data changeset
      IO.puts search.near_location.latitude
    ...
  end
end

The defparams macro generates a module for processing a params schema

By default all fields are optional. You can mark required fields by ending them with a !, of course the bang is removed from the field definition and is only used to mark which fields are required by default.

You can also create a module and define your schema or custom changesets in it:

defmodule UserSearch do
  use Params.Schema, %{name: :string, age: :integer}
  import Ecto.Changeset, only: [cast: 3, validate_inclusion: 3]

  def child(ch, params) do
    cast(ch, params, ~w(name age))
    |> validate_inclusion(:age, 1..6)
  end
end

defmodule MyApp.UserController do

  def index(conn, params) do
    changeset = UserSearch.from(params, with: &UserSearch.child/2)
    if changeset.valid? do
      # age in 1..6
  end

end

The Params.data and Params.to_map can be useful for obtaining a struct or map from a changeset.

Note that Params.data and Params.to_map have different behaviour: data returns a struct which will include all valid params. to_map returns a map that only includes the submitted keys and keys with default values:

defmodule UserUpdateParams do
  use Params.Schema, %{
    name: :string,
    age: :integer,
    auditlog: [field: :boolean, default: true]
  }
end

changeset = UserUpdateParams.from(%{name: "John"})

Params.data(changeset) # => %UserUpdateParams{name: "John", age: nil, auditlog: true}
Params.to_map(changeset) # => %{name: "John", auditlog: true}

API Documentation

API Documentation

Contributors

Here's a list of awesome people who have contributed code to this project.

If you find a bug or want to improve something, please send a pull-request. Thank you!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].