- Historic personal use of Active Record pattern in PHP, Rails, iOS dev.
- Ecto described itself as a toolkit for data mapping and language integrated query for Elixir.
- Changeset were (for me) a new concept that I've really come to appriciate.
Many of the demos you'll see come from Ecto's own Getting Started and I encourage you to check it out as well.
https://hexdocs.pm/ecto/getting-started.html
https://hexdocs.pm/ecto/Ecto.Changeset.html
Changesets allow filtering, casting, validation and definition of constraints when manipulating structs.
Mix.install([
{:ecto, "~> 3.6"},
{:etso, "~> 0.1.5"}
])
defmodule Friends.Repo do
use Ecto.Repo, otp_app: :friends, adapter: Etso.Adapter
end
Friends.Repo.start_link([])
defmodule Friends.Person do
use Ecto.Schema
schema "people" do
field(:first_name, :string)
field(:last_name, :string)
field(:age, :integer)
end
end
person = %Friends.Person{}
person = %Friends.Person{age: 28}
person = %Friends.Person{first_name: "Mike", last_name: "Zornek", age: 21}
Friends.Repo.insert(person)
# Can't reopen a previous module in a LiveBook.
defmodule PersonTools do
def changeset(person, params \\ %{}) do
person
|> Ecto.Changeset.cast(params, [:first_name, :last_name, :age])
|> Ecto.Changeset.validate_required([:first_name, :last_name])
end
end
person = %Friends.Person{age: 25}
changeset = PersonTools.changeset(person, %{})
{:error, result_changeset} = Friends.Repo.insert(changeset)
result_changeset.data
The public fields are:
valid?
- Stores if the changeset is validdata
- The changeset source data, for example, a structparams
- The parameters as given on changeset creationchanges
- Thechanges
from parameters that were approved in castingerrors
- All errors from validationsrequired
- All required fields as a list of atomsaction
- The action to be performed with the changesettypes
- Cache of the data's field typesempty_values
- A list of values to be considered emptyrepo
- The repository applying the changeset (only set after a Repo function is called)repo_opts
- A keyword list of options given to the underlying repository operation
The following fields are private and must not be accessed directly.
validations
constraints
filters
prepare
Lots of validation options: https://hexdocs.pm/ecto/Ecto.Changeset.html#validate_acceptance/3
Handy database constraint tools: https://hexdocs.pm/ecto/Ecto.Changeset.html#unique_constraint/3
<%= form_for @changeset, Routes.short_link_path(@conn, :create), fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Could not create short link. See errors below.</p>
</div>
<% end %>
<p>Enter in the <%= label f, :long_link, "link", [style: "display: inline; font-weight:300"] %>
you would like shortened in the field below.</p>
<%= text_input f, :long_link %>
<%= error_tag f, :long_link %>
<div>
<%= submit "Create Short Link" %>
</div>
<% end %>
https://elixirfocus.com/posts/ecto-schemaless-changesets/
A common but brittle approach that creates strong dependencies across all the layers.
params = %{"sign_up" => %{"name" => "Mike", "email" => "[email protected]"}}
data = %{}
types = %{name: :string, email: :string}
# The data+types tuple is equivalent to %Registration{}
changeset =
{data, types}
|> Ecto.Changeset.cast(params["sign_up"], Map.keys(types))
|> Ecto.Changeset.validate_required([:name])
|> Ecto.Changeset.validate_length(:name, min: 1, max: 100)
https://elixirfocus.com/posts/ecto-schemaless-changesets/
Unknown challenge/homework of keeping validations DRY and dealing with issue where web form changeset WAS valid but DB version was not.
does this work? i can't figure out how to define config in a livebook.. i see you define
otp_app: :friends
, but where is:friends
configured??