<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="140414" data-post-id="140414">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="lguminski" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/lguminski/120/16356_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  lguminski
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Note that the hook injects a method __tagged(), and then list_tagged_modules() checks for the presence of the method in module. So it should always work, unless there is a clash with an existing method. That’s why the name of the method must be unique.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="140414" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/getting-a-list-of-tagged-modules/3804/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-140414" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="140414"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="230048" data-post-id="230048">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="RomanKotov" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/RomanKotov/120/25676_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  RomanKotov
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a href="https://hexdocs.pm/elixir/1.12/Protocol.html#module-reflection" rel="noopener nofollow ugc">Elxir Protocols have an interesting reflection feature</a>. It looks like <code>SomeProtocol.__protocol__(:impls)</code> and can return a <code>{:consolidated, modules}</code>. It shows all modules, that implement the protocol. You can use this to tag modules, like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defprotocol TagExample.Tagged do
  @spec tags(t()) :: [atom()]
  def tags(data)
end

defmodule TagExample.Tag do
  alias TagExample.Tagged

  defmacro __using__(_opts) do
    quote do
      Module.register_attribute(
        __MODULE__,
        :tag,
        persist: true,
        accumulate: true
      )

      defimpl TagExample.Tagged do
        def tags(_) do
          :attributes
          |&gt; @for.__info__()
          |&gt; Keyword.get(:tag, [])
        end
      end
    end
  end

  defimpl Tagged, for: Atom do
    def tags(module) do
      :attributes
      |&gt; module.__info__()
      |&gt; Keyword.get(:tag, [])
    end
  end

  @spec tagged_modules() :: [module()]
  def tagged_modules do
    modules =
      case Tagged.__protocol__(:impls) do
        {:consolidated, modules} -&gt;
          modules

        _ -&gt;
          Protocol.extract_impls(
            Tagged,
            :code.lib_dir()
          )
      end

    for module &lt;- modules,
        module.__info__(:attributes)
        |&gt; Keyword.has_key?(:tag),
        do: module
  end

  @spec modules_with_tag(tag :: atom()) :: [module()]
  def modules_with_tag(tag) do
    for module &lt;- tagged_modules(),
        module
        |&gt; Tagged.tags()
        |&gt; Enum.member?(tag),
        do: module
  end
end

defmodule TagExample.TaggedModule1 do
  use TagExample.Tag

  @tag :tag1
  @tag :tag2
end

defmodule TagExample.TaggedModule2 do
  use TagExample.Tag

  @tag :tag2
  @tag :tag3
end

# iex&gt; TagExample.Tag.tagged_modules()
# [TagExample.TaggedModule2, TagExample.TaggedModule1]

# iex&gt; TagExample.Tag.modules_with_tag(:tag2)
# [TagExample.TaggedModule2]

# iex&gt; TagExample.Tag.modules_with_tag(:nonexisting_tag)
# []
</code></pre>
<p>This example uses module attributes, but you can store tags somewhere else (possibly in methods).</p>
<p>I have also created a <a href="https://romankotov.com/articles/elixir-module-registry-via-protocols.html" rel="noopener nofollow ugc">blog post</a> with edge cases for this implementation.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="230048" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/getting-a-list-of-tagged-modules/3804/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-230048" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="230048"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>