RafalKostecki

RafalKostecki

Ecto.CastError, expected params to be a :map

Hi there!
I am the new one in Elixir. Lately, I constantly facing the Ecto.CastError, expected params to be a :map.

I created a GraphQL API suing Phoenix and Absinthe. My goal is to convert one struct into another and insert it into another table in database. I mean, I have X and i wanna modify them to become an Y data type and insert them to Y table in DB.

I wrote code below (maybe there is an easier/better way to achieve my goal)

requested_chars.ex

import Ecto.Query, warn: false
  alias AngotiaCatalogsApi.Repo

  alias AngotiaCatalogsApi.RequestedChars.Char, as: RChar
  alias AngotiaCatalogsApi.Chars.Char

defp push_to_prod(char) do
    req_char = elem(char, 1)
    prod_char = req_char
      |> Map.delete(:__meta__)
      |> Map.delete(:__struct__)
      |> Map.delete(:author)
      |> Map.delete(:id)

    prod_char_struct = struct(Char, prod_char)

    %Char{}
      |> Char.changeset(prod_char_struct)
      |> Repo.insert()
  end

Where Char is another db table struct.

char.ex

defmodule AngotiaCatalogsApi.Chars.Char do
  use Ecto.Schema
  import Ecto.Changeset
  alias AngotiaCatalogsApi.Chars.Statistics
  alias AngotiaCatalogsApi.Chars.Settings
  alias AngotiaCatalogsApi.Chars.Monolog
  alias AngotiaCatalogsApi.Chars.Dialog


  schema "chars" do
    field :name, :string
    field :_id, :string
    field :field_diameter, :integer
    field :type, :string, default: "static"
    field :choosed, :string
    field :has_visible_level, :boolean, default: true
    field :char_pic, :string
    field :mob_range, :string
    field :is_agressive_mob, :boolean
    embeds_one :statistics, Statistics, on_replace: :update
    embeds_one :settings, Settings, on_replace: :update
    embeds_many :monologs, Monolog, on_replace: :delete
    embeds_many :dialogs, Dialog, on_replace: :delete

    timestamps()
  end

  def changeset(char, attrs) do
    char
    |> cast(attrs, [:name, :_id, :field_diameter, :type, :choosed, :has_visible_level, :char_pic, :mob_range, :is_agressive_mob])
    |> validate_required([:name, :_id, :field_diameter, :choosed, :has_visible_level, :char_pic])
    |> cast_embed(:statistics, with: &Statistics.changeset/2)
    |> cast_embed(:settings, with: &Settings.changeset/2)
    |> cast_embed(:monologs, with: &Monolog.changeset/2)
    |> cast_embed(:dialogs, with: &Dialog.changeset/2)
  end  
end

Full stack trace:

"# Ecto.CastError at POST /graphiql\n\nException:\n\n    ** (Ecto.CastError) expected params to be a :map, got: `%AngotiaCatalogsApi.Chars.Char{__meta__: #Ecto.Schema.Metadata<:built, \"chars\">, _id: \"160d1867-605f-4949-a6f0-ce9e2de068d6\", char_pic: \"afwa\", choosed: \"NPC\", dialogs: [], field_diameter: 0, has_visible_level: true, id: nil, inserted_at: ~N[2021-01-26 17:00:40], is_agressive_mob: false, mob_range: nil, monologs: [], name: \"test1\", settings: %AngotiaCatalogsApi.Chars.Settings{id: \"a93830bd-912b-4e1b-9a20-1f9ba9fae56a\", resp_time: %AngotiaCatalogsApi.Chars.Settings.RespTime{id: \"b5b6507c-b23e-49a2-af33-c4174284c89c\", max: 130, min: 60}, time_of_occurance: %AngotiaCatalogsApi.Chars.Settings.TimeOfOccurance{id: \"2a9674f4-d804-4e4c-b8cd-d85caf9bedd9\", max: 24, min: 0}}, statistics: %AngotiaCatalogsApi.Chars.Statistics{attack: 1, attack_range: 1, attack_speed: 100, defence: 1, dexterity: 1, health: 1000, id: \"142460ee-bf0c-4654-8ea6-dbbf1f9f4200\", inteligence: 1, jink: 1, level: 1, speed: 1, strength: 1}, type: \"STATIC\", updated_at: ~N[2021-01-26 17:00:40]}`\n        (ecto 3.4.5) lib/ecto/changeset.ex:457: Ecto.Changeset.cast/4\n        (angotia_catalogs_api 1.0.0) lib/angotia_catalogs_api/chars/char.ex:30: AngotiaCatalogsApi.Chars.Char.changeset/2\n        (angotia_catalogs_api 1.0.0) lib/angotia_catalogs_api/requested_chars/requested_chars.ex:38: AngotiaCatalogsApi.RequestedChars.push_to_prod/1\n        (absinthe 1.5.1) lib/absinthe/resolution.ex:209: Absinthe.Resolution.call/2\n        (absinthe 1.5.1) lib/absinthe/phase/document/execution/resolution.ex:230: Absinthe.Phase.Document.Execution.Resolution.reduce_resolution/1\n        (absinthe 1.5.1) lib/absinthe/phase/document/execution/resolution.ex:185: Absinthe.Phase.Document.Execution.Resolution.do_resolve_field/3\n        (absinthe 1.5.1) lib/absinthe/phase/document/execution/resolution.ex:170: Absinthe.Phase.Document.Execution.Resolution.do_resolve_fields/6\n        (absinthe 1.5.1) lib/absinthe/phase/document/execution/resolution.ex:88: Absinthe.Phase.Document.Execution.Resolution.walk_result/5\n        (absinthe 1.5.1) lib/absinthe/phase/document/execution/resolution.ex:67: Absinthe.Phase.Document.Execution.Resolution.perform_resolution/3\n        (absinthe 1.5.1) lib/absinthe/phase/document/execution/resolution.ex:24: Absinthe.Phase.Document.Execution.Resolution.resolve_current/3\n        (absinthe 1.5.1) lib/absinthe/pipeline.ex:368: Absinthe.Pipeline.run_phase/3\n        (absinthe_plug 1.5.0) lib/absinthe/plug.ex:445: Absinthe.Plug.run_query/4\n        (absinthe_plug 1.5.0) lib/absinthe/plug.ex:258: Absinthe.Plug.call/2\n        (phoenix 1.5.7) lib/phoenix/router/route.ex:41: Phoenix.Router.Route.call/2\n        (phoenix 1.5.7) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2\n        (angotia_catalogs_api 1.0.0) lib/angotia_catalogs_api_web/endpoint.ex:1: AngotiaCatalogsApiWeb.Endpoint.plug_builder_call/2\n        (angotia_catalogs_api 1.0.0) lib/plug/debugger.ex:132: AngotiaCatalogsApiWeb.Endpoint.\"call (overridable 3)\"/2\n        (angotia_catalogs_api 1.0.0) lib/angotia_catalogs_api_web/endpoint.ex:1: AngotiaCatalogsApiWeb.Endpoint.call/2\n        (phoenix 1.5.7) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4\n        (cowboy 2.8.0) /home/kostek/Documents/Programming/angotia-catalogs/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2\n    \n\n## Connection details\n\n### Params\n\n    %{\"query\" => \"mutation {\\n  acceptRequestedChar(id: 68) {\\n    id\\n  }\\n}\", \"variables\" => %{}}\n\n### Request info\n\n  * URI: http://localhost:4000/graphiql\n  * Query string: \n\n### Headers\n  \n  * accept: application/json\n  * accept-encoding: gzip, deflate\n  * accept-language: en-US,en;q=0.5\n  * cache-control: no-cache\n  * connection: keep-alive\n  * content-length: 86\n  * content-type: application/json\n  * cookie: next-i18next=en\n  * host: localhost:4000\n  * origin: http://localhost:4000\n  * pragma: no-cache\n  * referer: http://localhost:4000/graphiql?variables=%7B%7D&query=mutation%20%7B%0A%20%20acceptRequestedChar(id%3A%2068)%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%7D\n  * user-agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0\n\n### Session\n\n    %{}\n"

I see that my struct properly refer to Ecto “chars” schema. So whats wrong?

Marked As Solved

RafalKostecki

RafalKostecki

Okey, I found out whats goin on.

Nicd was right about Map type. My error was due to nested Structs inside Map. So I needed to convert nested Struct into nested Map and everything works fine!

About conversion: Convert a nested struct into a nested map

Also Liked

Nicd

Nicd

The input parameter attrs in your code to Ecto.Changeset.cast/4 should be a map, not a struct. The point of the changeset functionality is to build a set of changes to a struct (the char struct that you also input). Providing the changes as a struct doesn’t really make sense then.

So, instead of passing a struct to the changeset function, just pass a map.

Where Next?

Popular in Questions Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement