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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yeah hard to believe there isn’t a single-changeset solution for this scenario.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="17379" 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/ecto-validating-belongs-to-association-is-not-nil/2665/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-17379" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="17379"
                     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="17385" data-post-id="17385">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="wojtekmach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/wojtekmach/120/999_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  wojtekmach
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Hex Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>it’s pretty hacky, but perhaps this would work for you?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Rating do
  # ...

  def changeset(rating, params \\ %{}) do
    cast(rating, params, ~w(rating place_id))
    |&gt; validate_required(~w(rating)a)
    |&gt; cast_or_constraint_assoc(:place)
  end

  defp cast_or_constraint_assoc(changeset, name) do
    {:assoc, %{owner_key: key}} = changeset.types[name]
    if changeset.changes[key] do
      assoc_constraint(changeset, name)
    else
      cast_assoc(changeset, name, required: true)
    end
  end
end
</code></pre>
<p>I’d stick to exposing two different changeset functions though (and probably have a 3rd private changeset function that has common stuff)</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="17385" data-batch-url="/posts/batch_likers">
                        7
                      </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/ecto-validating-belongs-to-association-is-not-nil/2665/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-17385" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="17385"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-solved cat-solved" title="Marked as solution"></div>
  </section>
</div>
    <div class="postbit" id="17386" data-post-id="17386">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dotdotdotPaul" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dotdotdotPaul/120/2481_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dotdotdotPaul
                    <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>Nice solution for keeping the shared validations all in one place.  Was just hoping there was a better “best practice”.  <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="17386" 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/ecto-validating-belongs-to-association-is-not-nil/2665/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-17386" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="17386"
                     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="17388" data-post-id="17388">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Don’t cast_assoc accept a required: true option?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="17388" 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/ecto-validating-belongs-to-association-is-not-nil/2665/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-17388" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="17388"
                     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="17389" data-post-id="17389">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dotdotdotPaul" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dotdotdotPaul/120/2481_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dotdotdotPaul
                    <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">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="15" data-topic="2665" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Don’t cast_assoc accept a required: true option?</p>
</blockquote>
</aside>
<p>It does, but then you can’t use the changeset by simply passing in the foreign key IDs (in this example, you couldn’t create a <code>Rating.changeset(%Rating{}, %{rating: 5, place_id: 42})</code> (because this causes an error during the cast_assoc, since :place isn’t being used).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="17389" 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/ecto-validating-belongs-to-association-is-not-nil/2665/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-17389" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="17389"
                     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="17391" data-post-id="17391">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I understsand now, thank you. <a class="mention" href="/u/wojtekmach" rel="nofollow">@wojtekmach</a> sounds like a good way to go about this.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="17391" 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/ecto-validating-belongs-to-association-is-not-nil/2665/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-17391" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="17391"
                     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="39808" data-post-id="39808">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="axelson" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/axelson/120/26351_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  axelson
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Scenic Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Even if we’re using wojtekmach’s solution aren’t we still missing a validation that some version of place as passed in? Either as <code>place</code> or <code>place_id</code>?</p>
<p>If we do want that validation along with the constraint do we have any options?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="39808" 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/ecto-validating-belongs-to-association-is-not-nil/2665/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-39808" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="39808"
                     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="39814" data-post-id="39814">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It does do that - if it is passed in as place_id it is validated with assoc_constraint; otherwise it is checked with cast_assoc required: true.</p>
<p>However the code as listed is really not complete because it does not handle updates to the record that do not include a change to the place; e.g. record is loaded from the db, place_id is set, but because place_id is not <em>changed</em> cast_assoc fails on it. In my project I’m using a slightly modified version that will pass the changeset if it contains the key (place_id) already:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    def cast_or_constraint_assoc(changeset, name) do
      {:assoc, %{owner_key: key}} = changeset.types[name]
      #assoc id was directly set? confirm its valid
      if changeset.changes[key] do
        assoc_constraint(changeset, name)
      else
        #assoc key is already present, and not changed? do nothing
        if Map.get(changeset.data, key) do
          changeset
        else
          #we need to insert a new assoc (or errors)
          cast_assoc(changeset, name, required: true)
        end
      end
    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="39814" data-batch-url="/posts/batch_likers">
                        4
                      </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/ecto-validating-belongs-to-association-is-not-nil/2665/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-39814" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="39814"
                     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 #18"></div>
  </section>
</div>
    <div class="postbit" id="60063" data-post-id="60063">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The second part of this comment, and the code was wrong…I don’t have that original project in front of me but I’ve since tried to use this code in another project and it does not work because the association doesn’t show up in the changes collection when it is just passed in update params as a map. I now think <a class="mention" href="/u/wojtekmach" rel="nofollow">@wojtekmach</a> original code is the best solution and I suspect the problem I had in the previous project was because I did not preload the association I was updating, or maybe I passed the name of database field rather than the name of the association, e.g. in this example it should be invoked in the changeset as <code>|&gt; cast_or_constraint_assoc(:place)</code></p>
<p>To save scrolling, this is the code I think is best:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"> defp cast_or_constraint_assoc(changeset, name) do
    {:assoc, %{owner_key: key}} = changeset.types[name]
    if changeset.changes[key] do
      assoc_constraint(changeset, name)
    else
      cast_assoc(changeset, name, required: true)
    end
 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="60063" 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/ecto-validating-belongs-to-association-is-not-nil/2665/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-60063" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="60063"
                     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 #19"></div>
  </section>
</div>
    <div class="postbit" id="74599" data-post-id="74599">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>For people looking for more validation, the code below works pretty well for me.<br>
Using this code helps when you want to deal with a new <code>Map</code> or an existing <code>Struct</code> or an existing id was given for the association…</p>
<pre><code>def put_or_cast_or_constraint_assoc(changeset, name) do
  {:assoc, %{owner_key: key, related: type}} = changeset.types[name] |&gt; IO.inspect

  if changeset.changes[key] do
    assoc_constraint(changeset, name)
  else
    case val = changeset.params[name |&gt; Atom.to_string] do
      %correct_type{} when correct_type == type -&gt;
        put_assoc(changeset, name, val)
      %wrong_type{} -&gt;
        add_error(changeset, name, "Wrong struct given to #{key}", given: wrong_type, wanted: type)
      %{} -&gt;
        cast_assoc(changeset, name, required: true)
      _ -&gt;
        add_error(changeset, name, "No valid #{name} nor #{key}")
    end
  end
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="74599" 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/ecto-validating-belongs-to-association-is-not-nil/2665/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-74599" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="74599"
                     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 #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/2665/load_more?page=3">Load more posts (5 remaining)</a>
</div></template></turbo-stream>