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?