trenpixster/addict

Ecto changesets

Closed this issue · 4 comments

In an effort to further look into both parameter sanitization at the controller level and validations at the model level, I had some discussions with José about changesets and they seem to be the way forward. His original proposal is outlined here and it has since been implemented into ecto (master). This is coupled with phoenix master as well which will be released as 0.10 this weekend (per chrismccord).

My proposal is to created Addict.User that is useed in a developer-specified user model that adds the various changeset functions (see José's proposal) we need to validate parameters in AddictController. These changeset functions will also provide direct tie in with validations for both predefined and custom validations as well. Two birds; one stone. 😄

Documentation for ecto changesets can be found here.

Any thoughts on this approach?

From José's proposal, here is an example of model and controller implementation of changesets:

Controller:

plug :scrub_params, "user" when action in [:create, :update]
plug :action

def new(conn, %{"id" => id}) do
  changeset = User.changeset %User{}
  render conn, "new.html", changeset: changeset
end

def create(conn, %{"id" => id, "user" => params}) do
  changeset = User.changeset %User{}, params

  if changeset.valid? do
    user = Repo.insert(changeset)
    redirect conn, to: user_path(conn, :index)
  else
    render conn, "new.html", changeset: changeset
  end
end

Model:

defmodule User do
  use Ecto.Model

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

  def changeset(user, params \\ nil) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> validate_number(:age, more_than: 18)
    |> validate_unique(:email)
  end
end

Love it! 👍

kball commented

I would very much like this as well, as I'm trying to add some additional validation & transformation on a registration prior to passing into Addict (e.g. a password validation field, combining username and email, etc).

@trestrantham have you made any forward progress on this approach? If not, mind if I take a look at doing it?