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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="AndrewDryga" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/AndrewDryga/120/2784_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  AndrewDryga
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Here is our implementation: <a href="https://gist.github.com/AndrewDryga/72f2cdd366265afb4c0528935fa96927" class="inline-onebox" rel="noopener nofollow ugc">Dynamic embeds with Ecto · GitHub</a>. It’s used in production and did not cause any issues yet. It’s very hacky though.</p>
<p>Notice that we explicitly call <code>load_dynamic_embed/2</code> function every time schema is loaded from DB. We also dump everything to string-keyed map if changeset is valid to mimic behaviour of writing and reading from DB (so that you can compare <code>user == inserted_user</code> in test cases, otherwise string- and atom-keyed maps would be a problem).</p>
<p>If embedded changeset has an error it looks very much like nested schema was defined by using embeds_one/many`.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="177882" 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/dynamic-embeds-in-ecto/16403/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-177882" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="177882"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="177889" data-post-id="177889">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="AndrewDryga" data-post="22" data-topic="16403">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/andrewdryga/48/2784_2.png" class="avatar"> AndrewDryga:</div>
<blockquote>
<p>Our cast is different, in the raw Ecto schema we have a <code>type</code> field and then <code>payload</code> field which should be casted depending on <code>type</code> field value. Which Ecto does not allow as you can’t access <code>type</code> value while casting/dumpin/loading <code>payload</code> field.</p>
</blockquote>
</aside>
<p>Why not just copy the <code>type</code> field into the payload? You could do that in the changeset, before calling cast of a custom type.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="177889" 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/dynamic-embeds-in-ecto/16403/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-177889" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="177889"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="177925" data-post-id="177925">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="AndrewDryga" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/AndrewDryga/120/2784_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  AndrewDryga
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>There are few reasons:</p>
<ul>
<li>One is that in PostgreSQL using index on regular column and JSONb column at the same query is expensive (at least it was back when we designed embeds) - we do query data by type;</li>
<li>Back then, casting by using <code>Ecto.Type</code> was not flexible enough to cover our needs either;</li>
<li>For me, it just feels weird to have JSON field that holds information about itself, because <code>type</code> for us is strictly field even when <code>payload</code> is empty.</li>
</ul> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="177925" 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/dynamic-embeds-in-ecto/16403/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-177925" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="177925"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="177947" data-post-id="177947">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="AndrewDryga" data-post="25" data-topic="16403">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/andrewdryga/48/2784_2.png" class="avatar"> AndrewDryga:</div>
<blockquote>
<p>One is that in PostgreSQL using index on regular column and JSONb column at the same query is expensive</p>
</blockquote>
</aside>
<p>I suggested to <strong>copy</strong> the type field, so you end up with the exact same structure in the DB, no difference for querying, i.e. a type and payload fields in the schema, in addition to a type in the payload to enable polymorphism. That small logic for copying the type would be done in the changeset.</p>
<aside class="quote no-group" data-username="AndrewDryga" data-post="25" data-topic="16403">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/andrewdryga/48/2784_2.png" class="avatar"> AndrewDryga:</div>
<blockquote>
<p>just feels weird to have JSON field that holds information about itself,</p>
</blockquote>
</aside>
<p>Resorting to non documented, private internals such as <code>Ecto.Embedded</code> struct and its fields (thus that might change and break your app) seems worse as a solution. Would you go for a minor weirdness, or a fragile hack?</p>
<aside class="quote no-group" data-username="AndrewDryga" data-post="25" data-topic="16403">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/andrewdryga/48/2784_2.png" class="avatar"> AndrewDryga:</div>
<blockquote>
<p>Back then, casting by using <code>Ecto.Type</code> was not flexible enough to</p>
</blockquote>
</aside>
<p>Indeed I don’t know about the limitations you faced back in 2018, as I wasn’t doing Elixir at that time.<br>
I see however that <em>ecto_poly</em> was released end 2017, so there were some possibilities.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="177947" 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/dynamic-embeds-in-ecto/16403/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-177947" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="177947"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></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>