Skip to content

Instantly share code, notes, and snippets.

@createdbypete
Last active November 24, 2019 10:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save createdbypete/2992fd5b84353d4eaabaa393c7abe0e9 to your computer and use it in GitHub Desktop.
Save createdbypete/2992fd5b84353d4eaabaa393c7abe0e9 to your computer and use it in GitHub Desktop.
defmodule Example.Survey do
import Ecto.Query, warn: false
alias Example.Repo
alias Example.Surveys.Survey
def create_survey(attrs \\ %{}) do
%Survey{}
|> Survey.changeset(attrs)
|> Repo.insert()
end
def change_survey(%Survey{} = survey) do
Survey.changeset(survey, %{})
end
end
defmodule Example.Surveys.Survey do
use Ecto.Schema
import Ecto.Changeset
schema "surveys" do
field :occurred_at, :utc_datetime
has_many :answers, Example.Surveys.Answer
end
@doc false
def changeset(survey, attrs) do
survey
|> cast(attrs, [:occurred_at])
|> cast_assoc(:answers, required: true)
|> validate_required([:occurred_at])
end
end
defmodule Example.Surveys.Question do
use Ecto.Schema
schema "questions" do
field :question, :string
has_many :answers, Example.Surveys.Answer
end
end
defmodule Example.Surveys.Answer do
use Ecto.Schema
import Ecto.Changeset
schema "answers" do
field :answer, :string
belongs_to :survey, Example.Surveys.Survey
belongs_to :question, Example.Surveys.Question
end
@doc false
def changeset(answer, attrs) do
answer
|> cast(attrs, [:answer, :question_id])
|> validate_required([:answer])
|> assoc_constraint(:question)
end
end
defmodule ExampleWeb.SurveyController do
use ExampleWeb, :controller
alias Example.Surveys
alias Example.Surveys.{Question, Answer, Survey}
def new(conn, _params) do
answers = for q <- Example.Repo.all(Question) do
%Example.Surveys.Answer{question: q, question_id: q.id}
end
changeset = Surveys.change_survey(%Survey{answers: answers})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"survey" => survey_params}) do
case Survey.create_survey(survey_params) do
{:ok, survey} ->
conn
|> put_flash(:info, "Survey created successfully.")
|> redirect(to: Routes.survey_path(conn, :show, survey))
{:error, %Ecto.Changeset{} = changeset} ->
answers =
for answer <- changeset.changes.answers do
question =
Example.Repo.get!(Example.Question, answer.changes.question_id)
%{answer | data: %Answer{question: question, question_id: question.id}}
end
changeset = %{changeset | changes: %{changeset.changes | answers: answers}}
render(conn, "new.html", changeset: changeset)
end
end
end
<%= 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 %>
<%= label f, :occurred_at %>
<%= datetime_select f, :occurred_at %>
<%= error_tag f, :occurred_at %>
<%= inputs_for f, :answers, fn a -> %>
<%= hidden_input a, :question_id %>
<%= label a, :answer, a.data.question.question %>
<%= number_input a, :answer %>
<%= error_tag a, :answer %>
<% end %>
<div>
<%= submit "Save" %>
</div>
<% end %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment