Двойные реализации протокола в зависимых проектах

У меня проблемы с консолидацией реализации протокола в моем проекте Elixir. Чтобы быть более конкретным, я использую Ecto и какой-то простой проект под названием Gold (не имеет большого значения атм). Проблема в том, что они оба (Ecto а также Gold) использовать Poison сериализовать Decimals (и реализовать надлежащий протокол).

Реализация для Ecto выглядит примерно так:

defimpl Poison.Encoder, for: Decimal do
    def encode(decimal, _opts), do: <<?", Decimal.to_string(decimal)::binary, ?">>
end

Во время разработки появляется предупреждение о дублировании модуля:

warning: redefining module Poison.Encoder.Decimal (current version loaded from /(...)/_build/dev/lib/gold/ebin/Elixir.Poison.Encoder.Decimal.beam)
  lib/ecto/poison.ex:2

Но когда я пытаюсь использовать, например, exrm чтобы создать релиз, то я получаю сообщения о том, что у меня есть duplicate_modules

===> Provider (release) failed with: {error,
                     {rlx_prv_assembler,
                      {release_script_generation_error,
                       systools_make,
                       {duplicate_modules,
                        [{{'Elixir.Poison.Encoder.Decimal',
                           gold,
                           "/(...)/rel/bitcoin_api/lib/gold-0.12.0/ebin"},
                          {'Elixir.Poison.Encoder.Decimal',
                           ecto,
                           "/(...)/rel/bitcoin_api/lib/ecto-2.0.2/ebin"}}]}}}}

Как мне с этим бороться? Дело в том, что я на самом деле использую свою собственную версию Goldтак что я могу вмешаться, чтобы исправить это как можно скорее. Я знаю, я могу просто добавить Ecto в Gold как зависимость, но это кажется немного излишним, просто реализовать один протокол, как это. Есть ли какой-нибудь макрос для проверки того, что модуль уже реализован?

0 ответов

Быстрое исправление может заключаться в том, чтобы обернуть реализацию Голда в Code.ensure_loaded?/1

unless Code.ensure_loaded?(Ecto) do
  defimpl Poison.Encoder, for: Decimal do
    def encode(decimal, _opts), do: <<?", Decimal.to_string(decimal)::binary, ?">>
  end
end

Это немного неприглядно, но тогда вам не нужно добавлять Ecto, просто проверьте, не было ли это уже что-то еще

Другие вопросы по тегам