<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Jod Product &amp; Engineering Docs Blog</title>
        <link>https://docs.teamjod.app/blog</link>
        <description>Jod Product &amp; Engineering Docs Blog</description>
        <lastBuildDate>Wed, 09 Jul 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Ensuring model association shapes throughout the application stack]]></title>
            <link>https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes</link>
            <guid>https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes</guid>
            <pubDate>Wed, 09 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Intro to Json Shapes]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="intro-to-json-shapes">Intro to Json Shapes<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#intro-to-json-shapes" class="hash-link" aria-label="Direct link to Intro to Json Shapes" title="Direct link to Intro to Json Shapes" translate="no">​</a></h2>
<p>We will consider simple</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-identitiesuser">GET /identities/user/<!-- -->:id<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#get-identitiesuser" class="hash-link" aria-label="Direct link to get-identitiesuser" title="Direct link to get-identitiesuser" translate="no">​</a></h3>
<p>For a simple endpoint like getting a single <code>Identities::User</code>, we would expect the response to be:</p>
<p><strong>Response:</strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  country_id: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  email: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  first_name: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  last_name: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  phone_code: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  mobile: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-orguser-profiles">GET /org/user-profiles/<!-- -->:id<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#get-orguser-profiles" class="hash-link" aria-label="Direct link to get-orguser-profiles" title="Direct link to get-orguser-profiles" translate="no">​</a></h3>
<p>We explore the difference cases of considering associations when getting a single <code>Org::UserProfile</code>.</p>
<p><strong>Response if we do not join tables in the backend:</strong></p>
<ul>
<li class="">simply rendering the attributes on the model <code>Org::UserProfile</code></li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id: ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  title: ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p><strong>Response if I join <code>Identities::User</code> in the backend:</strong></p>
<ul>
<li class=""><code>Org::UserProfile</code> belongs_to <code>Identities::User</code></li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id:  ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  user: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    first_name: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    last_name: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p><strong>Response if I join all associations of <code>Org::UserProfile</code> in the backend:</strong></p>
<ul>
<li class=""><code>Org::UserProfile</code> belongs_to <code>Identities::User</code></li>
<li class=""><code>Org::UserProfile</code> belongs_to <code>Company</code></li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id:  ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  user: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id: ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    first_name:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    last_name:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  company: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id: ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p><strong>Bad response:</strong></p>
<p>This is a badly designed response because there is no database backed model that follows the following format.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id: Org::UserProfile.id,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  first_name: Identities::User.first_name,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  last_name: Identities::User.last_name,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>The idea is to maintain the json "shape" to follow the backend models.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="problem-statement">Problem Statement<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#problem-statement" class="hash-link" aria-label="Direct link to Problem Statement" title="Direct link to Problem Statement" translate="no">​</a></h2>
<p>For every <code>careers_job_application</code>, I want to know who posted the <code>careers_job</code></p>
<!-- -->
<p>If I add another relationship to <code>careers_job_applications</code>, do I need to join all the tables?</p>
<!-- -->
<p>Since <code>AuthProvider</code> wraps the entire frontend application</p>
<ul>
<li class=""><code>AuthProvider</code> stores <code>Identities::User</code> and <code>Careers::UserProfile</code> and <code>Org::UserProfile</code> (depending where the user logs into)</li>
<li class="">Every page will know who is calling our backend API</li>
<li class="">This means that the backend doesn't need to join the identities user</li>
</ul>
<p>However, this only applies for only <code>Career::UserProfile</code> cases.</p>
<p>For an <code>Org::UserProfile</code>, they would need to know names of <code>Careers::UserProfile</code></p>
<ul>
<li class="">For example, for each <code>Careers::JobApplication</code>, we would want to display the person name, which lives in <code>Identities::User</code></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-org-usercareersjob_applications">GET /org-user/careers/job_applications<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#get-org-usercareersjob_applications" class="hash-link" aria-label="Direct link to GET /org-user/careers/job_applications" title="Direct link to GET /org-user/careers/job_applications" translate="no">​</a></h3>
<ul>
<li class="">As a org user, I want to see who applied for my job</li>
</ul>
<p>Looking at the relationship:</p>
<!-- -->
<p>The person making this call is an org-user, I need to join the tables to display the name of the user who applied.</p>
<p>I would return the following response:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  careers_job_applications: [{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id:,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    //.. attributes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    career_user_profile: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      id: ..,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      identities_user: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        id: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        first_name: ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        last_name: ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-org-usercareersjob_applications-show">GET /org-user/careers/job_applications/<!-- -->:id<!-- --> (#show)<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#get-org-usercareersjob_applications-show" class="hash-link" aria-label="Direct link to get-org-usercareersjob_applications-show" title="Direct link to get-org-usercareersjob_applications-show" translate="no">​</a></h3>
<p>When showing a single job application:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  careers_job_applications</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//.. attributes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    career_user_profile</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">           ..</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      certificates</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .. </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      experiences</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .. </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      skills</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">       </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .. </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      identities_user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">         ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        first_name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        last_name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-can-we-reduce-joins-to-improve-performance">How can we reduce joins to improve performance?<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#how-can-we-reduce-joins-to-improve-performance" class="hash-link" aria-label="Direct link to How can we reduce joins to improve performance?" title="Direct link to How can we reduce joins to improve performance?" translate="no">​</a></h2>
<p>Add a json column <code>career_user_profiles.data</code>, every time we save a <code>Career::UserSomething</code> (i.e. skills, experiences, certificates), we update two tables:</p>
<ul>
<li class=""><code>Career::UserSomething</code> table</li>
<li class=""><code>Career::UserProfile.data</code> columns</li>
</ul>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  careers_job_applications</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//.. attributes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    career_user_profile</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ..</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      data</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// new column that pre-computes the "join" of the associated tables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        certificates</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .. </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        experience</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .. </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      identities_user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          first_name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ..</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          last_name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>The downside of this is that we require to update the tables whenever any one of the <code>Career::UserProfile</code> associations change.</p>
<ul>
<li class="">then again, it's fairly simple to ensure this by ensuring we call a, for example, <code>Careers::UserProfiles::UpdateDataService</code> in all the places that updates <code>Career::UserProfile</code> associations.</li>
</ul>
<!-- -->
<p><strong>Charlie Question</strong></p>
<p>Imagine we are in a company backend and frontend are two separate teams.</p>
<ul>
<li class="">I can see that response will always follow the convention where the payload will be correctly formatted (i.e. following the model "shape")</li>
<li class="">can frontend user ignore the shape when they are submitting the form?<!-- -->
<ul>
<li class="">I imagine frontend does not have visibility how it is implement in the backend</li>
</ul>
</li>
</ul>
<p>Backend creates endpoint:</p>
<ul>
<li class="">Send the postman doc to Frontend</li>
<li class="">Frontend would see it and implement their designs</li>
<li class="">Frontend realise in a particular page UI design, the endpoint provided does not return data from a specific model</li>
<li class="">Backend say i cannot join tables any more cause the response you got initially is already joining 10 tables</li>
<li class="">Backend will say, you call this other endpoint to get that model</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="so-what-have-we-established">So what have we established?<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#so-what-have-we-established" class="hash-link" aria-label="Direct link to So what have we established?" title="Direct link to So what have we established?" translate="no">​</a></h2>
<ul>
<li class="">The default API Response JSON "shape" should follow the model associations.</li>
<li class="">Ideally max up to <strong>3 table joins</strong> in the backend</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-does-this-model-association-json-shape-affect-forms-in-the-frontend">How does this "model association json shape" affect forms in the frontend?<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#how-does-this-model-association-json-shape-affect-forms-in-the-frontend" class="hash-link" aria-label="Direct link to How does this &quot;model association json shape&quot; affect forms in the frontend?" title="Direct link to How does this &quot;model association json shape&quot; affect forms in the frontend?" translate="no">​</a></h2>
<p>Forms should always follow the model it is rendering for.</p>
<p>If want to create a <code>Car</code>, I would have a <code>CarForm</code> that follows the Car attributes.</p>
<ul>
<li class="">one form field for each Car attribute.</li>
</ul>
<p>Likewise, if want to create a <code>Org::UserProfile</code>, I would have a <code>OrgUserProfileForm</code> that follows the <code>Org::UserProfile</code> attributes.</p>
<p><code>Org::UserProfile</code> Attributes</p>
<ul>
<li class="">id</li>
<li class="">identities_user (association)</li>
<li class="">company (association)</li>
<li class="">title</li>
<li class="">created_at</li>
<li class="">updated_at</li>
</ul>
<p>In my <code>&lt;OrgUserProfileForm&gt;</code>, I would need fields for the associations as well.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="scenario-1-admin">Scenario 1: Admin<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#scenario-1-admin" class="hash-link" aria-label="Direct link to Scenario 1: Admin" title="Direct link to Scenario 1: Admin" translate="no">​</a></h3>
<p>Assume <strong>Admin</strong> (jod staff) is creating an <code>Org::UserProfile</code>.</p>
<ul>
<li class="">Admin can access everything in the system<!-- -->
<ul>
<li class="">they can see all identities_users and companies</li>
</ul>
</li>
</ul>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Form</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TextInputField</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript string" style="color:#e3116c">'title'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">IdentitiesUserSelectField</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript string" style="color:#e3116c">'identities_user.id'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">CompanySelectField</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript string" style="color:#e3116c">'company'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Form</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:#d73a49">IdentitiesUserSelectField</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// makes an api call to GET /admin-user/identities/users</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// gets a list of identities</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// render the list of identities in a dropdown</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// user select 1 identity from the response</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// update the form OrgUserProfileForm state via react-hook-form</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>When I select a <code>Identities::User</code> and <code>Company</code> from their respective select fields</p>
<ul>
<li class="">my form state now has the <code>Identities::User</code> attributes and company attributes.</li>
<li class="">this means I can nicely render the models int he frontend after the user selects.</li>
</ul>
<p><img decoding="async" loading="lazy" alt="form-state-with-ui.drawio.svg" src="https://docs.teamjod.app/assets/images/form-state-with-ui.drawio-ffb15a01788651302a3dfbb377c68eb2.svg" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="scenario-2-org-user">Scenario 2: Org User<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#scenario-2-org-user" class="hash-link" aria-label="Direct link to Scenario 2: Org User" title="Direct link to Scenario 2: Org User" translate="no">​</a></h3>
<p>Assume <strong>Org User</strong> is creating an <code>Org::UserProfile</code>.</p>
<ul>
<li class="">Org User can only access everything associated with their company</li>
<li class="">They can only see <code>Identities::User</code> and a single <code>Company</code>, which is the company they belong to.</li>
</ul>
<p>Thinking about the form schema for <code>OrgUserProfileForm</code></p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>In the frontend, form is named as <code>{ModelName}Form</code></p></div></div>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">orgUserProfileSchema</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">title</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> zod</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// company_id: zod.integer()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">company</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> zod</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">integer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">required</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">identities_user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> zod</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">integer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:#d73a49">OrgUserProfileForm</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Form</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TextInputField</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript string" style="color:#e3116c">'title'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TextInputField</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">'identities_user</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">first_name</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Form</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  )</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">}</span><br></span></code></pre></div></div>
<p><strong>Yuri Question</strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Job Application &lt;-- we need to insert this</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">- User Career Profiles  &lt;-- we don't need to insert anything in this one</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   - User Career Experience &lt;-- we need to insert this</span><br></span></code></pre></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>While the question does not make sense in our domain, consider the same associations in the models.</p></div></div>
<p>I want to create a <code>Careers::JobApplication</code></p>
<ul>
<li class="">and at the same time create <code>Career::UserExperience</code></li>
</ul>
<p>Looking at the model associations (not the association on the database level)</p>
<!-- -->
<p>TL;DR: Yes we follow the format.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// form schema follow "shape"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> jobApplicationSchema </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">careers_job</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">careers_user_profile</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// we need to know who to create the Careers::UserExperience for</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token literal-property property" style="color:#36acaa">careers_experience</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token literal-property property" style="color:#36acaa">job_title</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Alternative form schema which does not consider "model association json-shape"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// While it's not wrong from a technical perspective, this is not our convention.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> jobApplicationSchema </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">careers_job_id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">careers_user_profile_id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">careers_experiences</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token spread operator" style="color:#393A34">...</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><strong>Imam Highlight:</strong></p>
<p>Whenever you change any form schema/state shape, ensure you are assigning errors to the correct form field names.</p>
<ul>
<li class="">this will ensure that errors are rendered on the correct field in the form</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="naming-things">Naming things<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#naming-things" class="hash-link" aria-label="Direct link to Naming things" title="Direct link to Naming things" translate="no">​</a></h2>
<!-- -->
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="july-direction">July Direction<a href="https://docs.teamjod.app/blog/2025/07/09/ensuring-model-association-shapes#july-direction" class="hash-link" aria-label="Direct link to July Direction" title="Direct link to July Direction" translate="no">​</a></h3>
<p><strong>Week 1</strong>
we will make changes to existing MVP based on the <strong>technical feedback</strong> from ali</p>
<ul>
<li class="">naming</li>
<li class="">api layer should not have async</li>
<li class="">form schema should follow endpoint structure/shape</li>
<li class="">endpoint should follow shape of model associations</li>
</ul>
<p><strong>Week 2</strong></p>
<ul>
<li class="">start on the peripheral services<!-- -->
<ul>
<li class="">send email</li>
<li class="">simple notification system</li>
<li class="">event/analytics</li>
<li class="">file upload</li>
</ul>
</li>
</ul>
<p><strong>Week 3</strong></p>
<ul>
<li class="">continue with peripherals</li>
<li class="">start on <strong>product feedback</strong></li>
</ul>
<p><strong>Week 4</strong></p>
<ul>
<li class="">continue on <strong>product feedback</strong></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Welcome]]></title>
            <link>https://docs.teamjod.app/blog/welcome</link>
            <guid>https://docs.teamjod.app/blog/welcome</guid>
            <pubDate>Thu, 26 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Docusaurus blogging features are powered by the blog plugin.]]></description>
            <content:encoded><![CDATA[<p><a href="https://docusaurus.io/docs/blog" target="_blank" rel="noopener noreferrer" class="">Docusaurus blogging features</a> are powered by the <a href="https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog" target="_blank" rel="noopener noreferrer" class="">blog plugin</a>.</p>
<p>Here are a few tips you might find useful.</p>
<p>Simply add Markdown files (or folders) to the <code>blog</code> directory.</p>
<p>Regular blog authors can be added to <code>authors.yml</code>.</p>
<p>The blog post date can be extracted from filenames, such as:</p>
<ul>
<li class=""><code>2019-05-30-welcome.md</code></li>
<li class=""><code>2019-05-30-welcome/index.md</code></li>
</ul>
<p>A blog post folder can be convenient to co-locate blog post images:</p>
<p><img decoding="async" loading="lazy" alt="Docusaurus Plushie" src="https://docs.teamjod.app/assets/images/docusaurus-plushie-banner-a60f7593abca1e3eef26a9afa244e4fb.jpeg" width="1500" height="500" class="img_ev3q"></p>
<p>The blog supports tags as well!</p>
<p><strong>And if you don't want a blog</strong>: just delete this directory, and use <code>blog: false</code> in your Docusaurus config.</p>]]></content:encoded>
            <category>Facebook</category>
            <category>Hello</category>
            <category>Docusaurus</category>
        </item>
        <item>
            <title><![CDATA[MDX Blog Post]]></title>
            <link>https://docs.teamjod.app/blog/mdx-blog-post</link>
            <guid>https://docs.teamjod.app/blog/mdx-blog-post</guid>
            <pubDate>Sun, 01 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Blog posts support Docusaurus Markdown features, such as MDX.]]></description>
            <content:encoded><![CDATA[<p>Blog posts support <a href="https://docusaurus.io/docs/markdown-features" target="_blank" rel="noopener noreferrer" class="">Docusaurus Markdown features</a>, such as <a href="https://mdxjs.com/" target="_blank" rel="noopener noreferrer" class="">MDX</a>.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>Use the power of React to create interactive blog posts.</p></div></div>
<!-- -->
<p>For example, use JSX to create an interactive button:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">button onClick</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">alert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'button clicked!'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token maybe-class-name">Click</span><span class="token plain"> me</span><span class="token operator" style="color:#393A34">!</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">button</span><span class="token operator" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<button>Click me!</button>]]></content:encoded>
            <category>Docusaurus</category>
        </item>
        <item>
            <title><![CDATA[Long Blog Post]]></title>
            <link>https://docs.teamjod.app/blog/long-blog-post</link>
            <guid>https://docs.teamjod.app/blog/long-blog-post</guid>
            <pubDate>Wed, 29 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[This is the summary of a very long blog post,]]></description>
            <content:encoded><![CDATA[<p>This is the summary of a very long blog post,</p>
<p>Use a <code>&lt;!--</code> <code>truncate</code> <code>--&gt;</code> comment to limit blog post size in the list view.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>]]></content:encoded>
            <category>Hello</category>
            <category>Docusaurus</category>
        </item>
        <item>
            <title><![CDATA[First Blog Post]]></title>
            <link>https://docs.teamjod.app/blog/first-blog-post</link>
            <guid>https://docs.teamjod.app/blog/first-blog-post</guid>
            <pubDate>Tue, 28 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Lorem ipsum dolor sit amet...]]></description>
            <content:encoded><![CDATA[<p>Lorem ipsum dolor sit amet...</p>
<p>...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet</p>]]></content:encoded>
            <category>Hola</category>
            <category>Docusaurus</category>
        </item>
    </channel>
</rss>