Search code examples
elixirphoenix-frameworkecto

Update list of maps with function that returns tuple


I am using Elixir 1.8.0 and Ecto 3.0.7

I have a list of maps that that look like this

things = [
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-45-67-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-251234",
    instance_id: "i-1234",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.45.67.46",
    key_name: "some_key",
    launch_time: "2018-06-13T16:34:04.000Z",
    monitoring: "disabled",
    private_ip_address: "10.1.1.1",
    vpc_id: "vpc-9999"
  },
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-99-99-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-2522344",
    instance_id: "i-99999",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.99.99.99",
    key_name: "some_key",
    launch_time: "2018-06-13T16:34:04.000Z",
    monitoring: "disabled",
    private_ip_address: "10.1.1.2",
    vpc_id: "vpc-9999"
  }
]

I am attempting to insert this list into my database using Ecto.Repo.insert_all. This doesn't work as is, because I'm calling launch_time a utc_datetime and this is not a DateTime in my list.

I'm attempting to convert it to a DateTime, however, from_iso8601 returns a tuple, which, of course, doesn't work.

iex(12)> things |> Enum.map(fn elem ->
...(12)>         Map.update!(elem, :launch_time, &DateTime.from_iso8601/1)
...(12)>       end)
[
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-56-179-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-25110f45",
    instance_id: "i-0df401bc2d3b16d37",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.56.179.46",
    key_name: "salt_provisioning",
    launch_time: {:ok, #DateTime<2018-06-13 16:34:04.000Z>, 0},
    monitoring: "disabled",
    private_ip_address: "10.81.1.244",
    vpc_id: "vpc-07a5e160"
  },
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-56-179-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-25110f45",
    instance_id: "i-0df401bc2d3b16d37",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.56.179.46",
    key_name: "salt_provisioning",
    launch_time: {:ok, #DateTime<2018-06-13 16:34:04.000Z>, 0},
    monitoring: "disabled",
    private_ip_address: "10.81.1.244",
    vpc_id: "vpc-07a5e160"
  }
]

How can I get just the DateTime back in my pipe so that I can insert_all my list? Or does this require multiple steps?


Solution

  • Your existing code can be made to work with a little change, hope it fits your requirements:

    things |> Enum.map(fn elem ->
      {:ok, datetime, _} = DateTime.from_iso8601(elem[:launch_time])
      Map.put(elem, :launch_time, datetime)
    end)