elixir-lang/ecto — pull request #145 by zoips (2013-12-18 03:18:21+00:00)
Title: Make :list type translate into Postgres ARRAY

When trying to declare an entity field as type :list, like this:

```text
defmodule Accounts.Models.Account do
use Ecto.Model

queryable "accounts" do
field :name, :string
field :primaryEmail, :string
field :primaryPhone, :string
field :emails, { :list, :string }
end

validate account,
name: present(),
primaryEmail: present(),
primaryPhone: present()
end
```

and then trying to insert into the database I was getting back the error:

```text
=ERROR REPORT==== 16-Dec-2013::21:08:31 ===
Conn: POST /accounts
Reason: (exit) {{Ecto.InvalidEntity[entity: Accounts.Models.Account.Entity[model: Accounts.Models.Account, id: nil, name: "test account", primaryEmail: "foo@example.com", primaryPhone: "1234567890", emails: ["foo@example.com"]], field: :emails, type: {:list, {:ok, :string}}, expected_type: :list, reason: nil], [{Ecto.Repo.Backend, :"-validate_entity/1-fun-0-", 4, [file: '/home/matt/Projects/test/test_accounts_service/deps/ecto/lib/ecto/repo/backend.ex', line: 185]}, {Enum, :"-each/2-lists^foreach/1-0-", 2, [file: '/home/matt/Programs/elixir-0.11.2/lib/elixir/lib/enum.ex', line: 354]}, {Enum, :each, 2, [file: '/home/matt/Programs/elixir-0.11.2/lib/elixir/lib/enum.ex', line: 354]}, {Ecto.Repo.Backend, :create, 3, [file: '/home/matt/Projects/test/test_accounts_service/deps/ecto/lib/ecto/repo/backend.ex', line: 54]}, {Accounts.Service, :create_account, 1, [file: '/home/matt/Projects/test/test_accounts_service/lib/service.ex', line: 43]}, {Accounts.Service, :"-handle_call/3-fun-0-", 2, [file: '/home/matt/Projects/test/test_accounts_service/lib/service.ex', line: 19]}]}, {:gen_server, :call, [:accounts_service, {:create_account, [{"emails", ["foo@example.com"]}, {"name", "test account"}, {"primaryEmail", "foo@example.com"}, {"primaryPhone", "1234567890"}]}]}}
```

The relevant portion is:

```text
field: :emails, type: {:list, {:ok, :string}}, expected_type: :list, reason: nil]
```

I tracked into Ecto.Repo.Backend.validate_entity/1 wasn't properly handling all the returns from Ecto.Query.Util.value_to_type/1. Specifically with lists it was returning the above, then not matching the result, handing it back to the type validation and where it would fail (I think).

I added an arm to the case statement to match on { :ok { type, { :ok, list_element_type } } and then unilaterally made the syntax in the Entity type declaration for lists to be a tuple of { :list, list_element_type } representing the list element types.

I'm really new to Elixir, so some of this is cargo-cult, and I'm not convinced I wasn't just doing something wrong to begin with. I added tests to verify what I added, and all existing tests pasts (I think; I ran mix test and all those tests succeeded). I didn't try to see if I still got the errors with Elixir 0.12.0, but I did test the above with Elixir 0.12.0.