Compilation error in file

Can’t figure out what the issue is here:

== Compilation error in file lib/twitter_core/tweet_log.ex ==
** (CompileError) lib/twitter_core/tweet_log.ex:19: Twitter.Core.Tweet.struct/0 is undefined, cannot expand struct Twitter.Core.Tweet. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
lib/twitter_core/tweet_log.ex:17: (module)

Here’s the code:

defmodule Twitter.Core.TweetLog do
  alias Twitter.Core.{Tweet, TweetLog, User}

  defstruct [:user_id, tweets: %{}]

  def new(%User{id: user_id}, tweet \\ %{}) when user_id != nil do
    case Map.has_key?(tweet, :created) do
      false ->
        %TweetLog{user_id: user_id}

      _ ->
        %TweetLog{user_id: user_id}
        |> add_tweet(tweet)
    end
  end

  def add_tweet(
        %TweetLog{tweets: tweets, user_id: user_id} = tweet_list,
        %Tweet{} = tweet
      ) do
    id = UUID.uuid1()
    tweet = %{tweet | id: id, user_id: user_id}
    new_tweets = Map.put(tweets, id, tweet)

    {:ok, %TweetLog{tweet_list | tweets: new_tweets}}
  end

  def get_last(%TweetLog{tweets: tweets}) do
    [head | _tail] =
      Enum.sort(tweets, fn {_key1, tweet1}, {_key2, tweet2} ->
        case Date.compare(tweet1.created, tweet2.created) do
          :lt ->
            true

          _ ->
            false
        end
      end)

    {_key, tweet} = head
    tweet
  end

  def all_tweets(%TweetLog{tweets: tweets}) do
    Enum.map(tweets, fn {_tweet_id, tweet} ->
      tweet
    end)
  end

  def update_tweet(
        %TweetLog{tweets: tweets} = tweet_list,
        %Tweet{id: id} = tweet
      ) do
    case Map.fetch(tweets, id) do
      {:ok, _} ->
        tweet = %{tweet | id: id}
        new_tweets = Map.put(tweets, id, tweet)
        {:ok, %{tweet_list | tweets: new_tweets}}

      :error ->
        {:error, :nonexistent_tweet}
    end
  end

  def delete_tweet(%TweetLog{tweets: tweets} = tweet_list, %Tweet{id: tweet_id}) do
    case Map.fetch(tweets, tweet_id) do
      {:ok, _} ->
        new_tweets = Map.delete(tweets, tweet_id)
        {:ok, %{tweet_list | tweets: new_tweets}}

      :error ->
        {:error, :invalid_delete_operation}
    end
  end
end

Tweet struct exists:

defmodule Twitter.Core.Tweet do
  alias Twitter.Core.{Comment, Tweet, User}

  @enforce_keys [:content, :title]

  defstruct [
    :created,
    :comments,
    :content,
    :id,
    :likes,
    :title,
    :user_id
  ]

  def add_comment(
        %Tweet{comments: comments} = tweet,
        %User{id: user_id},
        text
      ) do
    id = UUID.uuid1()
    comment = Comment.new(id, user_id, text)
    new_comments = Map.put(comments, id, comment)
    %Tweet{tweet | comments: new_comments}
  end

  def delete_comment(%Tweet{comments: comments} = tweet, %Comment{id: comment_id}) do
    case Map.fetch(tweet.comments, comment_id) do
      {:ok, _} ->
        new_comments = Map.delete(comments, comment_id)
        {:ok, %{tweet | comments: new_comments}}

      :error ->
        {:error, :non_existent_comment}
    end
  end

  def new(content, title) when is_binary(content),
    do: %Tweet{
      created: Timex.now(),
      comments: %{},
      content: content,
      likes: MapSet.new(),
      title: title
    }

  def toggle_like(%Tweet{likes: likes} = tweet, %User{id: user_id}) do
    case Enum.find(likes, &(&1 == user_id)) do
      nil ->
        likes = MapSet.put(likes, user_id)
        %{tweet | likes: likes}

      _ ->
        likes = MapSet.delete(likes, user_id)
        %{tweet | likes: likes}
    end
  end

  def update_comment(
        %Tweet{comments: comments} = tweet,
        %Comment{id: comment_id},
        text
      ) do
    case Map.fetch(comments, comment_id) do
      {:ok, comment} ->
        new_comment = %{comment | text: text}
        new_comments = Map.put(comments, comment.id, new_comment)
        {:ok, %{tweet | comments: new_comments}}

      :error ->
        {:error, :non_existent_comment}
    end
  end
end

I prefer to use

alias __MODULE__

when aliasing to self. That would be

defmodule Twitter.Core.TweetLog do
  alias __MODULE__
  alias Twitter.Core.{Tweet, User}
..
defmodule Twitter.Core.Tweet do
  alias __MODULE__
  alias Twitter.Core.{Comment, User}.
3 Likes

That solved it! Thanks :slight_smile: