7
votes

web/models/post.ex

defmodule Baby.Post do
  use Baby.Web, :model

  schema "posts" do
    field :cover, :string
    field :email, :string
    field :firstname, :string
    field :lastname, :string
    field :birthday_day, :integer
    field :birthday_month, :integer
    field :birthday_year, :integer
    field :description, :string
    field :phone, :string

    timestamps
  end

  @required_fields ~w(email firstname lastname birthday_day birthday_month birthday_year description phone)
  @optional_fields ~w()

  @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 \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

web/controllers/post_controller.ex

defmodule Baby.PostController do

  use Baby.Web, :controller

  alias Baby.Post



  def new(conn, _params) do

    changeset = Post.changeset(%Post{})
    render conn, "new.html", changeset: changeset

  end

  def create(conn, %{"post" => post_params}) do

    changeset = Post.changeset(%Post{}, post_params)

    case Repo.insert(changeset) do 

        {:ok, _post} -> 
          conn
          |> put_flash(:info, "Ton annonce à bien été ajoutée")
          |> redirect(to: "/")

        {:error, changeset} ->
          IO.inspect changeset.valid?
          IO.inspect changeset.errors
          render(conn, "new.html", changeset: changeset)

    end

  end
end

web/templates/post/new.html.ex

<%= if @changeset.action do %>
  <div class="alert alert-danger">
    <p>Oops, something went wrong! Please check the errors below.</p>
  </div>
<% end %>

<%= form_for @changeset, post_path(@conn, :create), fn f -> %>

  <label for="email">Email</label><br/>
  <%= text_input f, :email %><br/><br/>

  <label for="email">Prénom</label><br/>
  <%= text_input f, :firstname %><br/><br/>
  <%= error_tag f, :firstname %>

  <label for="email">Nom de famille</label><br/>
  <%= text_input f, :lastname %><br/><br/>

  <label for="email">Date de naissance</label><br/>
  <%= text_input f, :birthday_day, placeholder: "Jour" %>
  <%= text_input f, :birthday_month, placeholder: "Mois" %>
  <%= text_input f, :birthday_year, placeholder: "Année" %>

  <br/><br/>
  <%= error_tag f, :birthday_day %>
  <%= error_tag f, :birthday_month %>
  <%= error_tag f, :birthday_year %>


  <label>Description</label><br/>
  <%= textarea f, :description %><br/><br/>
  <%= error_tag f, :description %>

  <label>Numéro de téléphone</label><br/>
  <%= text_input f, :phone %><br/><br/>
  <%= error_tag f, :phone %>

  <button type="submit">Ajouter mon annonce</button>

<% end %>

When I submit the form with empty inputs to create a new post, the errors returned are:

[birthday_day: "is invalid", birthday_month: "is invalid",
 birthday_year: "is invalid"]

I should have the errors for: email, firstname, lastname, description, phone too ...

1

1 Answers

9
votes

That's because when you submit a form without filling a field, an empty string is submitted. You need to use the scrub_params plug in the controller, which replaces empty fields with nils.

Add this to your controller:

plug :scrub_params, "post" when action in [:create]

This is what Phoenix generates by default in the mix phoenix.gen.html generator. (Well it generates when action in [:create, :update]; you may want to switch to that when you add an update action.)

The reason you still get validation errors for birthday_day, birthday_month, and birthday_year is because empty strings aren't valid integers.