3

I'm trying to create a release of my Phoenix application using Distillery and I've overridden the Poison Encoders for DateTime and NaiveDateTime to match the API requirements.

When I run mix release, my app compiles but I get an error during .boot generation.

Here is the stacktrace:

$> mix release
warning: variable "aliases" does not exist and is being expanded to "aliases()", please use parentheses to remove the ambiguity or change the variable name
  mix.exs:12

warning: variable "deps" does not exist and is being expanded to "deps()", please use parentheses to remove the ambiguity or change the variable name
  mix.exs:13

==> Assembling release..
==> Building release helios:1.0.0 using environment dev
==> One or more direct or transitive dependencies are missing from
    :applications or :included_applications, they will not be included
    in the release:

    :ex_admin
    :floki
    :geo
    :guardian
    :json_web_token
    :mogrify
    :phoenix_pubsub
    :scrivener_ecto
    :timex
    :timex_ecto

    This can cause your application to fail at runtime. If you are sure
    that this is not an issue, you may ignore this warning.

==> Release failed, during .boot generation:
        Duplicated modules:
        'Elixir.Poison.Encoder.NaiveDateTime' specified in poison and helios
        'Elixir.Poison.Encoder.Ecto.DateTime' specified in ecto and helios

Is there any way to override the Poison Encoders without running into this problem?

EDIT: Here are the encoders that I have:

  defimpl Poison.Encoder, for: Ecto.DateTime do
    def encode(datetime, options) do

      dt = datetime |> Ecto.DateTime.to_erl
      |> Timex.Timezone.convert("UTC")
      |> Timex.format("{ISO:Extended}")
      |> elem(1)

      <<?", dt::binary, ?">>
    end
  end

  defimpl Poison.Encoder, for: NaiveDateTime do
    def encode(datetime, options) do

      dt = datetime
      |> Timex.Timezone.convert("UTC")
      |> Timex.format("{ISO:Extended}")
      |> elem(1)

      <<?", dt::binary, ?">>
    end
  end

1 Answers1

2

You probably want to implement the protocol. The docs give this example:

defimpl Poison.Encoder, for: Person do
  def encode(%{name: name, age: age}, options) do
    Poison.Encoder.BitString.encode("#{name} (#{age})", options)
  end
end

If your unfamiliar with protocols, please post your custom encoders and we can help with the protocol.

EDIT:

So, after a lot of digging, it appears that Poison does not allow override base types. These already have an implementation in the package. So, when you override them in your project, your creating two versions of the beam files.

There is already this issue open against this issue.

Steve Pallen
  • 4,417
  • 16
  • 33
  • This is what I've currently done but I get a `duplicated modules` error. It seems like `Distillery` and `exrm` both don't like it if I override the encoders for `DateTime` and `NaiveDateTime` :/ – Rohith Varanasi Apr 21 '17 at 23:45
  • 1
    I presume your project is called `:helios`. The error message you are receiving indicates that you have a copy of the `Elixir.Poison.Encoder.NaiveDateTime` module local in your project. Same for the other module. Please check to make sure you don't have these modules in your project. BTW, the `defimpl` macro does not define the module, it only implements the protocol. If you don't have you own local copy, then I would recommend you try a `mix clean` and build your release again. You can also try a `mix release.clean` – Steve Pallen Apr 21 '17 at 23:53
  • I updated the post to include my custom encoders. I tried `mix clean` and `mix release.clean` and ran `mix release` again but was faced with the same errors again. BTW, thanks for the help, appreciate it! Also, love your work on ExAdmin, we use that too :) – Rohith Varanasi Apr 21 '17 at 23:57
  • 1
    There are only 2 things that I can think of that would case this issue. 1, you have a source file somewhere in your local project that contains a module definition for `Poison.Encoder.NaiveDateTime`, or 2. you have a beam file kicking around that is getting picked up by mix release. If you have already done a grep in your project for `Poison.Encoder.NaiveDateTime`, then you an remove `deps` and `_build` folders. Then run `mix do deps.get, compile` – Steve Pallen Apr 22 '17 at 00:02
  • So I don't have any module definition for `Poison.Encoder.NaiveDateTime` when I grep in my `web` and `lib` folders. However, they do show up in my `_build` directory as `.beam` files in both `_build/dev/lib/helios` and `_build/dev/lib/poison` and `_build/dev/consolidated` – Rohith Varanasi Apr 22 '17 at 00:15
  • Try deleting the beam files in `_build/dev/lib/helios` folder. Also, I presume you are building the release for dev environment. – Steve Pallen Apr 22 '17 at 00:18
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/142318/discussion-between-rohith-varanasi-and-steve-pallen). – Rohith Varanasi Apr 22 '17 at 00:20