依赖项目中的重复协议实现

Kel*_*all 11 decimal elixir ecto exrm elixir-poison

我在Elixir项目中整合协议实现时遇到问题.更具体地说,我使用了Ecto一些简单的项目Gold(无关紧要).问题是,它们(EctoGold)都Poison用于序列化Decimals(并实现适当的协议).

Ecto外观的实现有点像这样:

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

在开发期间,有一个警告说该模块是重复的:

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
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用例如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"}}]}}}}
Run Code Online (Sandbox Code Playgroud)

我应该怎么处理这个?这里的情况是我实际使用我自己的版本Gold,所以我可以篡改它来尽快解决它.我知道我可以再补充EctoGold作为依赖,但似乎有点矫枉过正,只是实现一个协议是这样的.是否有某种宏来检查模块是否已经实现?

sdc*_*sdc 1

一个快速解决方案可能是将 Gold 的实现包装在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
Run Code Online (Sandbox Code Playgroud)

它有点恶心,但你不必添加 Ecto,只需检查是否有其他东西已经将其拉入即可