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
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)
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}
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