michaelwa

michaelwa

ExAws.Dynamo.Encoder and Ecto.Schema do not work together

My mix.exs dependencies (partial list):
{:ex_aws, “~> 2.1”},
{:ex_aws_dynamo, “~> 4.0”},
{:hackney, “~> 1.9”},
{:configparser_ex, “~> 4.0”}I created an Ecto.Schema:

I can create dyanmo tables, insert, update, and delete records just fine as long as the data records are derived from generic structs.

However, when I create an Ecto.Schema

defmodule IntandemWww.Users.User do
use Ecto.Schema
import Ecto.Changeset

@derive [ExAws.Dynamo.Encodable]

schema “users” do
field :name, :string, virtual: true
field :first_name, :string
field :middle_name, :string
field :last_name, :string
field :condition, :string
field :email, :string
field :phone, :string
field :status, :string
field :mentor, :string
field :enrollment_date, :string

timestamps()

end
end

Instance looks like this (note the “meta” attribute):

%Users.User{
meta: #Ecto.Schema.Metadata<:built, “users”>,
id: nil,
name: nil,
first_name: nil,
middle_name: nil,
last_name: nil,
condition: nil,
email: nil,
phone: nil,
status: nil,
mentor: nil,
enrollment_date: nil,
inserted_at: nil,
updated_at: nil
}

Then when I try to Encode it (with some actual data set though):

Dynamo.Encoder.encode!(new_user)

I get the following error:

** (Protocol.UndefinedError) protocol ExAws.Dynamo.Encodable not implemented for #Ecto.Schema.Metadata<:built, “users”> of type Ecto.Schema.Metadata (a struct). This protocol is implemented for the following type(s): Atom, BitString, Float, HashDict, Users.User, Integer, List, Map, MapSet, User
(ex_aws_dynamo 4.2.1) lib/ex_aws/dynamo/encodable.ex:1: ExAws.Dynamo.Encodable.impl_for!/1
(ex_aws_dynamo 4.2.1) lib/ex_aws/dynamo/encodable.ex:5: ExAws.Dynamo.Encodable.encode/2
(ex_aws_dynamo 4.2.1) lib/ex_aws/dynamo/encodable.ex:87: anonymous fn/2 in ExAws.Dynamo.Encodable.Map.do_encode/1
(stdlib 4.0.1) maps.erl:411: :maps.fold_1/3
(ex_aws_dynamo 4.2.1) lib/ex_aws/dynamo/encodable.ex:64: ExAws.Dynamo.Encodable.Map.encode/2

I looked through the encoder.ex in the ex_aws_dynamo dependency and the “meta” field is obviously not accounted for during encoding.

Is anyone using Ecto.Schema with Dynamo and if so how? Is this an oversight or were they not meant to ever work together?

I do not see any usage of the “options” that are passed to “encode” functions. Would a valid solution be to add “ignore_fields” as an array of fields to skip over?

Most Liked

michaelwa

michaelwa

Thank you!! Thank you! This gets me moving forward again!!

This worked!

@derive {ExAws.Dynamo.Encodable, only: [:name, :first_name, :middle_name, :last_name, :condition, :email, :phone, :status, :mentor, :enrollment_date, :inserted_at, :updated_at]}

I note that right below:

def do_encode(map, only: only) do

That there is an “except”:

def do_encode(map, except: except) do

I tried the three variants below. They all compile but no happiness!

@derive {ExAws.Dynamo.Encodable, except: [Ecto.Schema.Metadata]}
@derive {ExAws.Dynamo.Encodable, except: [:__meta__]}
@derive {ExAws.Dynamo.Encodable, except: ["__meta__"]}

I also see in the Ecto.Schema module the following:

Module.put_attribute(__MODULE__, :ecto_struct_fields, {:__meta__, meta})

So I would have guessed the :atom version should have worked.

al2o3cr

al2o3cr

(Note: I edited your post to use ``` to preserve code-formatting, underscores etc)

The encode function accepts an except option, but that’s distinct from the code generated when you say @derive {ExAws.Dynamo.Encodable, etc etc etc}.

What you want would be something like:

extractor =
  cond
    only = options[:only] ->
      quote(do: Map.take(struct, unquote(only)))

    except = options[:except] ->
      quote(do: :maps.without(unquote(except), struct))

    true ->
      quote(do: :maps.remove(:__struct__, struct))

and then you could say:

# NOTE TO FUTURE GOOGLERS: THIS LINE REQUIRES THE CHANGE ABOVE!
@derive {ExAws.Dynamo.Encodable, except: [:__struct__, :__meta__]}

This could make a good PR to ExAws.Dynamo, if you added some tests. Maybe :except should automatically add :__struct__ :thinking:

Where Next?

Popular in Questions Top

LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Kagamiiiii
Student &amp; New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
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
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement