Last active
September 10, 2016 02:41
-
-
Save jmichalicek/85fd1bac89f6ec9620af54f210c1a05a to your computer and use it in GitHub Desktop.
Form for a model and related child models in Phoenix 1.2 and Ecto 2.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Child do | |
use MyApp.Web, :model | |
schema "child" do | |
field :name, :string | |
field :description, :string | |
belongs_to :event, MyApp.Parent | |
timestamps | |
end | |
@doc """ | |
Creates a changeset based on the `model` and `params`. | |
If no params are provided, an invalid changeset is returned | |
with no validation performed. | |
""" | |
def changeset(model, params \\ %{}) do | |
model | |
|> cast(params, [:name, :description]) | |
|> cast_assoc(:parent, required: True) | |
|> validate_required([:name, ]) | |
end | |
def nested_changeset(model, params \\ %{}) do | |
# Does not try to cast the parent assoc | |
model | |
|> cast(params, [:name, :description]) | |
|> validate_required([:name, ]) | |
end | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Parent do | |
use MyApp.Web, :model | |
schema "parent" do | |
field :name, :string | |
field :description, :string | |
has_many :children, MyApp.Child | |
timestamps | |
end | |
@error_messages %{ | |
:name => %{ | |
:required => "Please include a name." | |
}, | |
:description => %{ | |
:required => "Please include a short description." | |
} | |
} | |
def error_messages, do: @error_messages | |
def changeset(model, params \\ %{}) do | |
model | |
|> cast(params, [:name, :description]) | |
|> validate_required(:name, message: @error_messages.name.required) | |
|> validate_required(:description, message: @error_messages.description.required) | |
|> cast_assoc(:location_choices, with: &MyApp.Child.nested_changeset/2) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= form_for @changeset, @action, fn f -> %> | |
<%= if @changeset.action do %> | |
<div class="alert alert-danger"> | |
<p>Oops, something went wrong! Please check the errors below.</p> | |
</div> | |
<% end %> | |
<div class="form-group"> | |
<%= label f, :name, class: "control-label" %> | |
<%= text_input f, :name, class: "form-control" %> | |
<%= error_tag f.source, :name %> | |
</div> | |
<div class="form-group"> | |
<%= label f, :description, class: "control-label" %> | |
<%= textarea f, :description, class: "form-control" %> | |
<%= error_tag f.source, :description %> | |
</div> | |
<hr> | |
<h3>Children</h3> | |
<%= inputs_for f, :children, [append: [Child.nested_changeset(%Child{})]], fn fp -> %> | |
<div class="form-group"> | |
<%= label fp, :name, class: "control-label" %> | |
<%= text_input fp, :name, class: "form-control" %> | |
<%= error_tag fp, :name %> | |
</div> | |
<div class="form-group"> | |
<%= label fp, :description, class: "control-label" %> | |
<%= text_input fp, :description, class: "form-control" %> | |
<%= error_tag fp, :description %> | |
</div> | |
<% end %> | |
<div class="form-group"> | |
<%= submit "Submit", class: "btn btn-primary" %> | |
</div> | |
<% end %> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.ParentController do | |
use MyApp.Web, :controller | |
alias MyApp.Parent | |
import Ecto.Changeset | |
plug :scrub_params, "parent" when action in [:create, :update] | |
def new(conn, params,) do | |
changeset = Parent.changeset(%Parent{}) | |
render(conn, "new.html", changeset: changeset) | |
end | |
def create(conn, %{"parent" => params}, user) do | |
changeset = Parent.changeset(%Parent{}, params) | |
case Repo.insert(changeset) do | |
{:ok, parent} -> | |
conn | |
|> put_flash(:info, "Event created successfully.") | |
|> redirect(to: parent_path(conn, :show, parent)) | |
{:error, changeset} -> | |
render(conn, "new.html", changeset: changeset) | |
end | |
end | |
def edit(conn, %{"id" => id}) do | |
event = Repo.get!(Parent, id) |> Repo.preload(:children) | |
changeset = Parent.changeset(parent) | |
render(conn, "edit.html", parent: parent, changeset: changeset) | |
end | |
def update(conn, %{"id" => id, "parent" => params}, user) do | |
parent = Repo.get!(Parent, id) |> Repo.preload(:children) | |
changeset = Parent.changeset(parent, params) | |
case Repo.update(changeset) do | |
{:ok, parent} -> | |
conn | |
|> put_flash(:info, "Parent updated successfully.") | |
|> redirect(to: event_path(conn, :edit, parent)) # just going back to edit because it is simple example | |
{:error, changeset} -> | |
render(conn, "edit.html", parent: parent, changeset: changeset) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment