Двойные реализации протокола в зависимых проектах
У меня проблемы с консолидацией реализации протокола в моем проекте 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, просто проверьте, не было ли это уже что-то еще