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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I doubt there even is a solution, which could be recommended without knowing context. Personally I feel the need for highly customizable queries is a sign of to few functions. If I need the profile of an user I would say querying <code>Accounts.User |&gt; Accounts.include_user_profile()</code> is not the way – <code>Profiles.fetch_for_user(user_id)</code> should be. On the other hand there are people using absinthe api’s, which is basically the complete opposite: Query whatever you want as long as it’s somehow related to each other.</p>
<p>There are tradeoffs to be made between more options on functions vs. more functions, separation vs. coupling and even runtime concerns, like limiting query counts.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188320" 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/balancing-elixir-context-design-with-flexible-web-apis/33989/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-188320" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188320"
                     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="188324" data-post-id="188324">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>When you have the requirement for flexible queries, but want to use contexts for well defined update operations, then a <a href="https://martinfowler.com/bliki/CQRS.html" rel="noopener nofollow ugc">CQRS</a> approach might be worth considering.</p>
<p>By having separate code paths for queries and commands, you can optimise each along different dimensions.</p>
<p>You can start with separating the controllers for the index and show actions. Those will be primarily concerned with composing the appropriate ecto query to serve the request efficiently.</p>
<p>The controller for the other actions would be primarily concerned with validating parameters, possibly building a struct that represents the command and passing that into your context module.</p>
<p>Unfortunately CQRS is often introduced in the context of event sourcing, but I think it can be valuable on its own.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188324" data-batch-url="/posts/batch_likers">
                        3
                      </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/balancing-elixir-context-design-with-flexible-web-apis/33989/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-188324" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188324"
                     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 #12"></div>
  </section>
</div>
    <div class="postbit" id="188328" data-post-id="188328">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I am exploring some ideas similar to <a class="mention" href="/u/baldwindavid" rel="nofollow">@baldwindavid</a>’s TokenOperator (wasn’t aware the library existed when I started). The API is slightly different, and I’ve not tested it on production yet, so for real production usage TokenOperator is probably a better fit, but it looks something like this (Midas is placeholder name for now).</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Blog do
 def list_posts(opts \\ []) do
    Post
    |&gt; query()
    |&gt; Midas.new(opts)
    |&gt; Midas.add(:id, fn q, %{id: id} -&gt; queryable |&gt; where([q], q.id == ^id) end
    |&gt; Midas.add(:user_id, &amp;user_id_query/2)
    |&gt; Repo.all()
  end
end
</code></pre>
<p>I took some inspiration from Ecto.Multi and Absinthe, using Multi’s token approach and Absinthe’s resolver idea, I think the API looks rather clean while being pretty obvious what is happening when you read the context code. You are declaring options, and have resolvers that can resolve these options (just like how absinthe resolve fields).</p>
<p>My ideal usage would be to hide the query logic from controllers/absinthe resolvers, I don’t think they should know about what queries to run, so I disagree with baldwindavid’s approach where the controller specify queries to run. That way controllers only talk to the context function, and it doesn’t actually know how the data is resolved (whether it be Ecto, API or something else).</p>
<p>My current usage is to definite a lot of named functions, (list_published_posts etc), and then reuse and compose Ecto queries, this just sort of simplifies it into one interface.</p>
<p>Maybe this can give you some idea.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188328" data-batch-url="/posts/batch_likers">
                        1
                      </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/balancing-elixir-context-design-with-flexible-web-apis/33989/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-188328" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188328"
                     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 #13"></div>
  </section>
</div>
    <div class="postbit" id="188421" data-post-id="188421">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Had some time to work on it this week so I went ahead and published it, check it out: <a href="https://github.com/edisonywh/condiment" class="inline-onebox" rel="noopener nofollow ugc">GitHub - edisonywh/condiment: 🍡 Add flavors to your context function without the hassles. · GitHub</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188421" 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/balancing-elixir-context-design-with-flexible-web-apis/33989/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-188421" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188421"
                     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 #14"></div>
  </section>
</div>
    <div class="postbit" id="188492" data-post-id="188492">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Congrats on the project! However, I disagree with your base premise here. Having explicit functions is better for project clarity than “magic” that infers things and gives you a pretty one liner – this is exactly what Rails does with ActiveRecord (it’s got much less magical over the years though). Pulling in an external dependency to “solve” a non-problem creates even more complexity as people now need to be aware of how to work with an extra dependency.</p>
<p>Ecto provides us with composable queries out of the box which is already amazing, we don’t need to add another abstraction on top of that. If you need, have a <code>Blog.PostQuery</code> module where you add all of your queries and then compose with them on your <code>Blog.Posts</code> context. I do this extensively in this project: <a href="https://github.com/pedromtavares/moba/blob/master/lib/moba/game/heroes.ex" rel="noopener nofollow ugc">Base Module</a> - <a href="https://github.com/pedromtavares/moba/blob/master/lib/moba/game/query/hero_query.ex" rel="noopener nofollow ugc">Query Module</a> and it feels very intuitive and most importantly – explicit.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188492" 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/balancing-elixir-context-design-with-flexible-web-apis/33989/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-188492" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188492"
                     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 #15"></div>
  </section>
</div>
    <div class="postbit" id="188515" data-post-id="188515">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks!</p>
<p>I totally agree that Ecto’s composable queries are amazing. In fact, I still use them with <code>Condiment</code> now, but I don’t agree with <code>Condiment</code> being “magic”.</p>
<p>It is considered magic in ActiveRecord because they hide the actual implementation detail from you, as a user, it’s great because it’s simple, but then it’s a headache trying to figure out what exactly gets run. With Condiment it is extremely obvious what each field resolves to, because you explicitly whitelist a list of options (visible on the context module), and you explicitly pass it a resolver (inline or anonymous function). As a user, you just request things you want, and if you ever want to figure out what actually gets run, you can look at the context module and it’s easy to see what conditions ran too.</p>
<p>I understand it’s not for everyone’s taste, and a huge reason I love Elixir so much is exactly because of the explicitness compared to Ruby/Rails, but like I said, I don’t think Condiment is magic at all (I consider magic to be something you need to jump through multiple files just to understand how the data is flowing, requiring a lot of contexts at each step, so mostly things like macros). If anything, I think of Condiment as more like a pattern.</p>
<p>Thanks for the examples! I really like the idea of a QueryModule, right now in my projects it’s just mostly a bunch of <code>*_query</code> functions in the Context module. With your approach of a query module I would be able to remove the <code>_query</code> suffix and still communicate the intent well (<code>Query.search</code>). Will be using this idea at some point <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188515" data-batch-url="/posts/batch_likers">
                        1
                      </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/balancing-elixir-context-design-with-flexible-web-apis/33989/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-188515" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188515"
                     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 #16"></div>
  </section>
</div>
    <div class="postbit" id="188516" data-post-id="188516">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I usually just use <code>Enum.reduce</code>. E.g. for the example you used in your readme:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def list_posts(opts \\ []) do
  Enum.reduce(opts, posts_query(), fn
    {:featured, featured}, query -&gt; featured_query(query, featured)
    {:user_id, id}, query -&gt; by_user_query(query, id)
    _, query -&gt; query
  end)
  |&gt; Repo.all()
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188516" data-batch-url="/posts/batch_likers">
                        3
                      </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/balancing-elixir-context-design-with-flexible-web-apis/33989/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-188516" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188516"
                     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 #17"></div>
  </section>
</div>
    <div class="postbit" id="188519" data-post-id="188519">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yup like I pointed out in the README, it’s basically a glorified <code>Enum.reduce</code> with some slight difference, some examples being:</p>
<ul>
<li>with Enum.reduce your reduction runs in the order user specified</li>
<li>you get some niceties like validating the options user passed in is valid</li>
<li>I’d argue that the API is a bit better (your function retains the same shape, rather than having to rearrange everything to fit <code>Enum.reduce</code>)</li>
</ul>
<p>The package itself is very small!</p>
<p>For now I’ve ported my app <a href="http://slickinbox.com/" rel="noopener nofollow ugc">http://slickinbox.com/</a> to use Condiment and I really like it</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="188519" 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/balancing-elixir-context-design-with-flexible-web-apis/33989/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-188519" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="188519"
                     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>