How to change struct names

Hi guys,

I have the next struct:

%StructMapTest.Line{
a: “2”,
b: “4.0”
}

and I want to change it into:

%Line{
a: “2”,
b: “4.0”
}

Can anyone let me know how to do it?

Thanks in advance,

Thiel

Struct names are stored in :__struct__, so you can change that.

%StructMapTest.Line{
  a: “2”,
  b: “4.0”
}.__struct__
#=> StructMapTest.Line

But why?

I learning Amnesia and therefore I am trying to make a simple program that reads
records from a file. These records should go into an Amnesia database.

I enclose some code:

defmodule StructMapTest do
use ExUnit.Case

NimbleCSV.define(MyParser, separator: “,”, escape: “”")

#---------------------------------------------------------------

defdatabase Database do

deftable Lines, [:a , :b, :c], type: :set do

end

#---------------------------------------------------------------

defmodule Line do
defstruct [a: “”, b: “”, c: “”]
end

#---------------------------------------------------------------

test “Struct -from - map” do

result =
File.stream!("/home/thiel/memdata.csv")

|> MyParser.parse_stream

|> Stream.map(fn [a, b, c] ->
%{
a: a,
b: b,
c: c
}
end)

Now I want to convert a map into a struct

for a_map <- result do

line = MapToStruct.struct_from_map(a_map, as: %Line{})

end

end

end

#---------------------------------------------------------------

At the end I want to do the next test:

test “saves lines” do
IO.write"\nDatabase test - saves a lines
Amnesia.transaction! do
rec = %Line{ a: 1.0, b: 2.0, c: 3.0}
rec |> Line.write
end

I was not sure if %StructMapTest.Line would do the job.

May be you can give this super-idiot a clue what should be done.

Many thanks in advance,

Thiel

You can wrap your code blocks in ``` to display them as code

```
# your
# code
# block
```

Oops, I forget it.

The most idiomatic way is to do this:

bar = %Bar{a: 0, b: :c}
%Foo{a: bar.a, b: bar.c}

Fiddling with :__struct__ relies on an implementation detail of elixir, also it might bring you data into an invalid state.

Just consider %Foo{} Beeing defined as [:a, :b, :c] and %Bar{} is only [:a, :b] and you do %{bar | __struct__: Foo} you’ll have a malformed struct:

iex(1)> defmodule A do
...(1)>   defstruct [:a]
...(1)> end
{:module, A,
 <<70, 79, 82, 49, 0, 0, 5, 112, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 178,
   0, 0, 0, 18, 8, 69, 108, 105, 120, 105, 114, 46, 65, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 9, 102, 117, 110, 99, ...>>, %A{a: nil}}
iex(2)> defmodule B do
...(2)>   defstruct [:a, :b]
...(2)> end
{:module, B,
 <<70, 79, 82, 49, 0, 0, 5, 120, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 178,
   0, 0, 0, 18, 8, 69, 108, 105, 120, 105, 114, 46, 66, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 9, 102, 117, 110, 99, ...>>, %B{a: nil, b: nil}}
iex(3)> a = %A{a: 1}
%A{a: 1}
iex(4)> b = %{a | __struct__: B}
%{__struct__: B, a: 1}
1 Like

I am learning the Amnesia system and I solved my problem I could not write records from a CSV file to an Amnesia database.

Here is code snippet that did the job:

results =
  File.stream!("/home/thiel/mydata.csv")

  |> MyParser.parse_stream
  
  |> Stream.map(fn [dag, hoog, laag, slot, omzet, dummy] -> 
    a_map = %{
     dag:   dag,
     hoog:  hoog,
     laag:  laag,
     slot:  slot,
     omzet: omzet,
     dummy: dummy}
     end)
  
  for a_map <- results do 
  
    line = struct(Database.Koersen, a_map) 

    Amnesia.transaction do

    line |> Koersen.write 
     
   end
   
  end
   
  assert( Amnesia.transaction do
    assert Koersen.read("1") == %Koersen{dag: "1", hoog: "46.75", laag: "48.50",
                                slot: "45.45", omzet: "48.40", dummy: "20.0"}
    end == true)
  
   end