Append data to list on an association

Hello, as the title says, I have a table that belongs to another one, this table (The association) has a column which is a list, what I want to do is append data to that list whenever a command is executed, the first time it works, I can append the first element to the list but after that it throws me an error saying that the type is invalid, that it is a map. (I’m using Postgres if that matters)

Error reason on censor command: #Ecto.Changeset<action: :update, changes: %{},
 errors: [censored_words: {"is invalid", [type: {:array, :map}]}],
 data: #Censorex.DB.Guild<>, valid?: false>

My concern here is, why does it accept it as a map the first time, converts it to the type that the field is but when I try it a second time it complains? I mean, I can see that I’m passing a map when I should pass a list. But how can I pass the information to the changeset if that is causing the error then?

I’ve tried several “solutions” and I ended up with a not too good looking code for this task. Here’s piece that makes that task.

def censor(msg) do
    [_| tail] = String.split(msg.content, " ")
    censored = %{
                  id: get_censor_id(Helpers.get_guild_id(msg.channel_id)),
                  words: [Enum.join(tail, " ")]
    IO.inspect censored, label: "Censored var"

    message =
      with guild <- Repo.get_by(Guild, guild: Helpers.get_guild_id(msg.channel_id))
                    |> Repo.preload(:censored_words),
           changeset <- Changeset.change(guild)
                    |> Changeset.put_assoc(:censored_words, flatten_words(guild) ++ [censored]),
           {:ok, _struct} <- Repo.update(changeset) do
        "**New command added**"
        {:error, reason} ->
          IO.inspect(reason, label: "Error reason on censor command")
          "**There was an error trying to register your command**"
        _ -> ":x:"

    Api.create_message(msg.channel_id, message)

  # Priv

  # This function is here because I was getting the list elements as a 2D list and when I tried to
  # append it, I ended up with a weird looking list.
  defp flatten_words(list) do
    |> List.flatten
    |> IO.inspect(label: "Flatten words lists")

  # And this one is because I was getting an error saying that I needed to pass the id of the
  # association to the map above (censored variable)
  defp get_censor_id(guild_id) do
    guild =
      |> Repo.get_by(guild: guild_id)
      |> Repo.preload(:censored_words)

    |> List.first
    |> IO.inspect(label: "Censor id")

I don’t know if you need to see the schema for this but here they are just in case:


defmodule Censorex.DB.Guild do
  @moduledoc false

  use Ecto.Schema

  import Ecto.Changeset

  alias Censorex.DB

  schema "guild" do
    field :owner, :integer
    field :guild, :integer

    has_many :censored_words, DB.Censored


  def changeset(model, params \\ %{}) do
    |> cast(params, [:owner, :guild])
    |> unique_constraint(:guild)


defmodule Censorex.DB.Censored do
  @moduledoc false

  use Ecto.Schema

  alias Censorex.DB

  schema "censored" do
    field :words, {:array, :string}, default: []
    field :guild_id, :integer

    belongs_to :guild, DB.Guild, define_field: false


Thanks for any help ^-^