Записать экто схему в файл csv в эликсире? - PullRequest
0 голосов
/ 22 сентября 2018

Привет, у меня есть схема Person в эликсире, как это

[
  %Texting.Contact.Person{
    __meta__: #Ecto.Schema.Metadata<:loaded, "people">,
    email: nil,
    name: "John",
    phone_number: "13334445555",
    phonebook: #Ecto.Association.NotLoaded<association :phonebook is not loaded>,
    phonebook_id: 60,
    previous_phonebook_id: 60,
    subscribed: true,
    updated_at: ~N[2018-09-22 14:36:04.788163],
    user: #Ecto.Association.NotLoaded<association :user is not loaded>,
    user_id: 54
  },
  %Texting.Contact.Person{
    __meta__: #Ecto.Schema.Metadata<:loaded, "people">,
    email: nil,
    name: "Rhee",
    phone_number: "14443335555",
    phonebook: #Ecto.Association.NotLoaded<association :phonebook is not loaded>,
    phonebook_id: 60,
    previous_phonebook_id: 60,
    subscribed: true,
    updated_at: ~N[2018-09-22 14:36:13.671479],
    user: #Ecto.Association.NotLoaded<association :user is not loaded>,
    user_id: 54
  }
]

И я хочу сохранить это в формате файла CSV. Так что я сделал это

def write!(people) do
    file = File.open("contacts.csv", [:write, :utf8])
    people
    |> Enum.map(&Map.from_struct(&1))
    |> Enum.map(&CSV.encode(&1, headers: [:name, :phone_number]))
    |> Enum.map(&IO.write(file, &1))
end

, но я получил ошибкукак это

** (Protocol.UndefinedError) protocol String.Chars not implemented for #Function<62.51129937/2 in Stream.transform/3>. This protocol is implemented for: Atom, BitString, Date, DateTime, Decimal, Ecto.Date, Ecto.DateTime, Ecto.Time, Float, Floki.Selector, Floki.Selector.AttributeSelector, Floki.Selector.Combinator, Floki.Selector.Functional, Floki.Selector.PseudoClass, Integer, List, NaiveDateTime, Postgrex.Copy, Postgrex.Query, Postgrex.Stream, Time, URI, Version, Version.Requirement
    (elixir) /home/ubuntu/bob/tmp/0a92cc555e2418d1b56e3b10e5321a85/elixir/lib/elixir/lib/string/chars.ex:3: String.Chars.impl_for!/1
    (elixir) /home/ubuntu/bob/tmp/0a92cc555e2418d1b56e3b10e5321a85/elixir/lib/elixir/lib/string/chars.ex:22: String.Chars.to_string/1
    (elixir) lib/io.ex:553: IO.write/2
    (elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2

Что я хочу сделать, это сохранить только имя и поле phone_number в формате файла CSV.Как я могу это сделать?

1 Ответ

0 голосов
/ 22 сентября 2018

Согласно документации , CSV.encode/2 принимает список списка строк и не имеет опции, которую вы пытались использовать.

Вот как я это сделаю:

def write!(people) do
  people
  |> Stream.map(&[&1.name, &1.phone_number])
  |> CSV.encode()
  |> Enum.into(File.stream!("contacts.csv"))
end

Enum.map создает список списка строк, который затем кодируется и передается в contacts.csv.

Чтобы добавить строку заголовка вверху, вы можете использовать Stream.concat/2 для добавления строки заголовка:

def write!(people) do
  [["name", "phone_number"]]
  |> Stream.concat(people |> Stream.map(&[&1.name, &1.phone_number]))
  |> CSV.encode()
  |> Enum.into(File.stream!("contacts.csv"))
end
...