Created
July 23, 2021 17:26
-
-
Save TylerPachal/9599485f9a103aeb3dda5f16419feb21 to your computer and use it in GitHub Desktop.
Comparing the Ecto return value to what Phoenix renders
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
# When using Ecto Schemas for validating, I wanted to see what error information was present in the | |
# Ecto.Changeset, and then compare that to what Phoenix would render by default. | |
# | |
# Q: Can you get the index of nested objects' errors? | |
# A: Yes, for nested lists anything valid will have an empty entry in the list, while invalid | |
# objects will have some error information. Either way you could use Enum.with_index() to figure | |
# out a specific index. | |
## lib/phoenix_playground/accounts/user.ex | |
defmodule PhoenixPlayground.Accounts.User do | |
use Ecto.Schema | |
import Ecto.Changeset | |
alias PhoenixPlayground.Accounts.Pet | |
embedded_schema do | |
field :age, :integer | |
field :name, :string | |
embeds_many :pets, Pet | |
timestamps() | |
end | |
@doc false | |
def changeset(user, attrs) do | |
user | |
|> cast(attrs, [:name, :age]) | |
|> cast_embed(:pets, required: true) | |
|> validate_required([:name, :age]) | |
|> validate_number(:age, greater_than_or_equal_to: 0, less_than: 110) | |
|> validate_length(:pets, min: 1) | |
end | |
end | |
## lib/phoenix_playground/accounts/pet.ex | |
defmodule PhoenixPlayground.Accounts.Pet do | |
use Ecto.Schema | |
import Ecto.Changeset | |
embedded_schema do | |
field :type, :string | |
field :name, :string | |
timestamps() | |
end | |
@doc false | |
def changeset(user, attrs) do | |
user | |
|> cast(attrs, [:name, :type]) | |
|> validate_required([:name, :type]) | |
|> validate_inclusion(:type, ["dog", "cat"]) | |
end | |
end | |
## lib/phoenix_playground_web/controllers/user_controller.ex | |
defmodule PhoenixPlaygroundWeb.UserControllerTest do | |
use PhoenixPlaygroundWeb.ConnCase | |
alias PhoenixPlayground.Accounts.User | |
setup %{conn: conn} do | |
{:ok, conn: put_req_header(conn, "accept", "application/json")} | |
end | |
# ----- Missing Fields ----- | |
@missing_fields %{} | |
test "schema - create - missing fields" do | |
%Ecto.Changeset{errors: errors} = User.changeset(%User{}, @missing_fields) | |
assert [ | |
name: {"can't be blank", [validation: :required]}, | |
age: {"can't be blank", [validation: :required]}, | |
pets: {"can't be blank", [validation: :required]} | |
] == errors | |
end | |
test "API - create - missing fields", %{conn: conn} do | |
conn = post(conn, Routes.user_path(conn, :create), user: @missing_fields) | |
assert %{ | |
"age" => ["can't be blank"], | |
"name" => ["can't be blank"], | |
"pets" => ["can't be blank"] | |
} == json_response(conn, 422)["errors"] | |
end | |
# ----- Incorrect Types ----- | |
@incorrect_types %{"name" => false, "age" => [], "pets" => "dogs are great"} | |
test "schema - create - incorrect types" do | |
%Ecto.Changeset{errors: errors} = User.changeset(%User{}, @incorrect_types) | |
assert [ | |
pets: {"is invalid", [validation: :embed, type: {:array, :map}]}, | |
name: {"is invalid", [type: :string, validation: :cast]}, | |
age: {"is invalid", [type: :integer, validation: :cast]} | |
] == errors | |
end | |
test "API - create - incorrect types", %{conn: conn} do | |
conn = post(conn, Routes.user_path(conn, :create), user: @incorrect_types) | |
assert %{ | |
"age" => ["is invalid"], | |
"name" => ["is invalid"], | |
"pets" => ["is invalid"] | |
} == json_response(conn, 422)["errors"] | |
end | |
# ----- Nested Error ----- | |
@nested_error %{ | |
"name" => "tyler", | |
"age" => 28, | |
"pets" => [ | |
%{"name" => "rio", "type" => "dog"}, | |
%{"name" => "frank", "type" => "hotdog"}, | |
%{"name" => "joshua", "type" => "cat"}, | |
%{"name" => "fluffy", "type" => "lobster"} | |
] | |
} | |
test "schema - create - nested error" do | |
%Ecto.Changeset{valid?: false, changes: %{pets: pets}} = User.changeset(%User{}, @nested_error) | |
assert [ | |
%{valid?: true}, | |
%{valid?: false}, | |
%{valid?: true}, | |
%{valid?: false} | |
] = pets | |
end | |
test "API - create - nested error", %{conn: conn} do | |
conn = post(conn, Routes.user_path(conn, :create), user: @nested_error) | |
assert %{ | |
"pets" => [ | |
%{}, | |
%{"type" => ["is invalid"]}, | |
%{}, | |
%{"type" => ["is invalid"]} | |
] | |
} == json_response(conn, 422)["errors"] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment