Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Readme appears wrong and api won't initialize #21

Open
scottmessinger opened this issue Sep 12, 2019 · 4 comments
Open

Readme appears wrong and api won't initialize #21

scottmessinger opened this issue Sep 12, 2019 · 4 comments

Comments

@scottmessinger
Copy link

Hi!

Thanks for creating this! I'm trying to get it working and am running into some issues.

First, there is not Prismic.V2.API. That commit to the README happened early in the life of the project and, as far as I can tell, there has never been a Prismic.V2 module.

Second, when I try to init the api (or do Prismic.all), I get this:

iex(6)> Prismic.api("https://my-repo.cdn.prismic.io/api/v2")
** (Protocol.UndefinedError) protocol Enumerable not implemented for 
%Prismic.API{access_token: nil, bookmarks: nil, forms: nil, refs: [%Prismic.Ref{id: nil, isMasterRef: false, label: nil, ref: nil, scheduledAt: nil}], repository_url: "https://cc-homepage.cdn.prismic.io/api/v2"}. 
This protocol is implemented for: [snip...]

I've added defimpl Enumerable, for: Prismic.Ref do ... and defimpl Enumerable, for: Prismic.API do... and then I just get ** (UndefinedFunctionError) function nil.__struct__/0 is undefined. If you are using the dot syntax, such as map.field or module.function, make sure the left side of the dot is an atom or a map.

Am I'm just grossly misunderstanding the API? Let me know!

@scottmessinger
Copy link
Author

Also, is if it helps, we're on Erlang 21 and Elixir 1.8.1

@newtrat
Copy link
Contributor

newtrat commented Sep 12, 2019

Could you post the stacktrace? You're not misunderstanding the API, and you shouldn't have to defimpl Enumerable anywhere.

@scottmessinger
Copy link
Author

@newtrat Thanks! Here's the stack trace. Sorry -- I should have included this initially!

    (elixir) /usr/local/src/elixir/lib/elixir/lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) /usr/local/src/elixir/lib/elixir/lib/enum.ex:141: Enumerable.reduce/3
    (elixir) lib/enum.ex:3015: Enum.reduce/3
    (poison) lib/poison.ex:70: Poison.decode/2
    lib/api.ex:23: Prismic.API.new/2

@newtrat
Copy link
Contributor

newtrat commented Sep 14, 2019

Sorry, I haven't been able to reproduce this bug yet. This is a long shot, but perhaps try clearing and reinstalling your dependencies with mix deps.clean --all followed by mix deps.get.

Here is some relevant code from Poison, version 3.1.0, as stored in my /deps. We're calling Decode.decode(value, options) where value is Prismic's API response parsed into a map, and options is [as: %API{repository_url: repo_url, refs: [%Ref{}]}, keys: :atoms].

I've included only the clauses that I think are actually getting called... though I could be wrong 🙂

defmodule Poison.Decode do
  def decode(value, options) when is_map(value) or is_list(value) do
    case options[:as] do
      nil -> value
      as -> transform(value, options[:keys], as, options)
    end
  end

  defp transform(value, keys, %{__struct__: _} = as, options) do
    transform_struct(value, keys, as, options)
  end

  defp transform_struct(value, keys, as, options) when keys in [:atoms, :atoms!] do
    as
    |> Map.from_struct
    |> Map.merge(value)
    |> do_transform_struct(keys, as, options)
  end

  defp do_transform_struct(value, keys, as, options) do
    default = struct(as.__struct__)

    as
    |> Map.from_struct
    |> Enum.reduce(%{}, fn {key, as}, acc ->
      new_value = case Map.fetch(value, key) do
        {:ok, ^as} when is_map(as) or is_list(as) ->
          Map.get(default, key)
        {:ok, value} when is_map(value) or is_list(value) ->
          transform(value, keys, as, options)
        {:ok, value} ->
          value
        :error ->
          Map.get(default, key)
      end

      Map.put(acc, key, new_value)
    end)
    |> Map.put(:__struct__, as.__struct__)
    |> Poison.Decoder.decode(options)
  end

What we're passing into Enum.reduce should be a plain map, since it goes through Map.from_struct right before the Enum.reduce call. But in your case we appear to be passing a Prismic.API struct instead.

Can you check out your deps/poison/lib/poison/decoder.ex and see how it matches up? Maybe it is missing the Map.from_struct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants