title: How do you set up an Ecto changeset to prevent models missing required fields from being saved?
body: <p>According to the Phoenix documentation:</p>
  
  <blockquote>
    <p>insert(Ecto.Schema.t | Ecto.Changeset.t, Keyword.t) ::   {:ok,
    Ecto.Schema.t} |   {:error, Ecto.Changeset.t}</p>
    
    <p>Inserts a model or a changeset.</p>
    
    <p>In case a model is given, the model is converted into a changeset with
    all model non-virtual fields as part of the changeset. This conversion
    is done by calling Ecto.Changeset.change/2 directly.</p>
    
    <p>In case a changeset is given, the changes in the changeset are merged
    with the model fields, and all of them are sent to the database.</p>
    
    <p>If any before_insert or after_insert callback is registered in the
    given model, they will be invoked with the changeset.</p>
    
    <p>It returns {:ok, model} if the model has been successfully inserted or
    {:error, changeset} if there was a validation or a known constraint
    error.</p>
  </blockquote>
  
  <h2>What I did</h2>
  
  <pre><code>defmodule Dollar.User do
      use Dollar.Web, :model
  
      schema "users" do
          field :username, :string
          field :sms_number, :string
          field :email, :string
  
          timestamps
      end
  
      @required_fields ~w(sms_number)
      @optional_fields ~w(username email)
  
      @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(user, params \\ :empty) do
          user
          |&gt; cast(params, @required_fields, @optional_fields)
          |&gt; validate_length(:sms_number, is: 10)
          |&gt; unique_constraint(:sms_number)
          |&gt; unique_constraint(:username)
      end
  end
  </code></pre>
  
  <h2>What I expected</h2>
  
  <pre><code>Repo.insert(%User{})
  =&gt; {:error, ... }
  </code></pre>
  
  <p>I expected an error because the <code>sms_number</code> is <strong>required</strong>.</p>
  
  <h2>What I actually got</h2>
  
  <pre class="lang-sh prettyprint-override"><code>[debug] INSERT INTO "users" ("inserted_at", "updated_at", "email", "sms_number", "username") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [{{2016, 3, 19}, {15, 13, 5, 0}}, {{2016, 3, 19}, {15, 13, 5, 0}}, nil, nil, nil] OK query=1.5ms
  %Dollar.User{__meta__: #Ecto.Schema.Metadata&lt;:loaded&gt;, email: nil, id: 7,
   inserted_at: #Ecto.DateTime&lt;2016-03-19T15:13:05Z&gt;, sms_number: nil,
   updated_at: #Ecto.DateTime&lt;2016-03-19T15:13:05Z&gt;, username: nil}
  </code></pre>
  
  <p>The record is stored in the database</p>
  
  <h2>Environment</h2>
  
  <ul>
  <li>Elixir 1.2.3</li>
  <li>Ecto 1.1.4</li>
  <li>Phoenix Ecto 2.0.1</li>
  <li>Phoenix 1.1.4</li>
  </ul>
  
  <p>What am I doing wrong?</p>