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 use
ed 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! 👍
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?