<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cris Joseph</title>
    <description>The latest articles on DEV Community by Cris Joseph (@cris_joseph_37bec69f4274b).</description>
    <link>https://dev.to/cris_joseph_37bec69f4274b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2134885%2Fd5f2a6d2-c119-46a8-8f2d-1a6ba66946fb.jpg</url>
      <title>DEV Community: Cris Joseph</title>
      <link>https://dev.to/cris_joseph_37bec69f4274b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cris_joseph_37bec69f4274b"/>
    <language>en</language>
    <item>
      <title>After 10 Years of Rails, Here's What AI Coding Agents Get Wrong (and How I Fixed It)</title>
      <dc:creator>Cris Joseph</dc:creator>
      <pubDate>Mon, 23 Mar 2026 04:43:46 +0000</pubDate>
      <link>https://dev.to/cris_joseph_37bec69f4274b/after-10-years-of-rails-heres-what-ai-coding-agents-get-wrong-and-how-i-fixed-it-4gni</link>
      <guid>https://dev.to/cris_joseph_37bec69f4274b/after-10-years-of-rails-heres-what-ai-coding-agents-get-wrong-and-how-i-fixed-it-4gni</guid>
      <description>&lt;p&gt;I’ve been writing Rails for ~10 years.&lt;br&gt;
I started using AI coding agents (Claude Code, Cursor) daily last year.&lt;/p&gt;

&lt;p&gt;And I kept hitting the same wall:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The agent can read files, but it doesn’t understand the app.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It sees &lt;code&gt;schema.rb&lt;/code&gt;, but not constraints.&lt;br&gt;
It sees controllers, but not inherited filters.&lt;br&gt;
It sees models, but not concerns, optional associations, or runtime behavior.&lt;/p&gt;

&lt;p&gt;Rails is &lt;strong&gt;convention over configuration&lt;/strong&gt; - which means the &lt;em&gt;real&lt;/em&gt; structure of the app is &lt;strong&gt;emergent at runtime&lt;/strong&gt;, not visible in any single file.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;rails-ai-context&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What rails-ai-context does
&lt;/h2&gt;

&lt;p&gt;Instead of dumping more files into the context window, it gives AI agents a &lt;strong&gt;structured, queryable introspection layer&lt;/strong&gt; via &lt;strong&gt;MCP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema (real schema, not just &lt;code&gt;schema.rb&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails_get_schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;table: &lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ columns, types, NOT NULL&lt;br&gt;
→ defaults&lt;br&gt;
→ indexes&lt;br&gt;
→ foreign keys&lt;/p&gt;

&lt;p&gt;Pulled from the &lt;strong&gt;live DB when available&lt;/strong&gt;, with a smart &lt;code&gt;schema.rb&lt;/code&gt; fallback.&lt;/p&gt;




&lt;h3&gt;
  
  
  Models (with concerns expanded)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails_get_model_details&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="s2"&gt;"Cook"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ associations (including &lt;code&gt;optional: true&lt;/code&gt;)&lt;br&gt;
→ validations&lt;br&gt;
→ scopes&lt;br&gt;
→ callbacks&lt;br&gt;
→ concern methods shown inline&lt;br&gt;
  &lt;code&gt;PlanLimitable → can_cook?, limits&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Controllers (actual execution path)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails_get_controllers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;controller: &lt;/span&gt;&lt;span class="s2"&gt;"cooks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action: &lt;/span&gt;&lt;span class="s2"&gt;"create"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ source of &lt;strong&gt;that one action only&lt;/strong&gt;&lt;br&gt;
→ inherited &lt;code&gt;before_action&lt;/code&gt;s across the controller hierarchy&lt;br&gt;
→ strong params body&lt;/p&gt;

&lt;p&gt;No guessing. No missing filters.&lt;/p&gt;




&lt;h3&gt;
  
  
  Semantic validation (Rails-aware)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails_validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;files: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;level: &lt;/span&gt;&lt;span class="s2"&gt;"rails"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Catches things static linters miss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-existent columns&lt;/li&gt;
&lt;li&gt;Missing partials&lt;/li&gt;
&lt;li&gt;Broken route helpers&lt;/li&gt;
&lt;li&gt;Undefined callbacks&lt;/li&gt;
&lt;li&gt;Missing FK indexes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;strong&gt;semantic validation&lt;/strong&gt;, not syntax checking.&lt;/p&gt;




&lt;h2&gt;
  
  
  The key insight
&lt;/h2&gt;

&lt;p&gt;Rails apps aren’t static.&lt;/p&gt;

&lt;p&gt;Their structure is defined by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schema constraints&lt;/li&gt;
&lt;li&gt;inherited filters&lt;/li&gt;
&lt;li&gt;concerns&lt;/li&gt;
&lt;li&gt;association options&lt;/li&gt;
&lt;li&gt;runtime reflection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI agents don’t need &lt;em&gt;more files&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;They need a &lt;strong&gt;structured query layer&lt;/strong&gt; that mirrors how Rails itself understands the app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture (high-level)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;29 introspectors → 13 read-only MCP tools + static context&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Three-layer progressive disclosure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static context files&lt;/strong&gt; (~150 lines)&lt;br&gt;
Loaded at session start — zero cost mental map&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Conditional rules&lt;/strong&gt; (&lt;code&gt;.cursor/rules/&lt;/code&gt;)&lt;br&gt;
Loaded only when relevant (model, controller, view, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Live MCP tools&lt;/strong&gt;&lt;br&gt;
Queried on demand with:&lt;br&gt;
&lt;code&gt;summary → standard → full&lt;/code&gt; detail levels&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;37% fewer tokens&lt;/strong&gt; on a real production app&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;First-attempt success rate&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: ~50%&lt;/li&gt;
&lt;li&gt;After: ~90%&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;But the real win is &lt;strong&gt;accuracy&lt;/strong&gt;, not token savings.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical notes (for the curious)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built on the &lt;strong&gt;official MCP Ruby SDK&lt;/strong&gt; (not a custom protocol)&lt;/li&gt;
&lt;li&gt;All tools are &lt;strong&gt;read-only&lt;/strong&gt; and annotated&lt;/li&gt;
&lt;li&gt;Sensitive files auto-blocked:
&lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;master.key&lt;/code&gt;, credentials&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ERB validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compiles ERB → Ruby&lt;/li&gt;
&lt;li&gt;Then syntax-checks the result&lt;/li&gt;
&lt;li&gt;Catches missing &lt;code&gt;&amp;lt;% end %&amp;gt;&lt;/code&gt; that &lt;code&gt;ERB.new.src&lt;/code&gt; misses&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Schema parser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live DB introspection first&lt;/li&gt;
&lt;li&gt;Text-based &lt;code&gt;schema.rb&lt;/code&gt; fallback&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Controller filter extraction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hybrid reflection + source parsing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;510 tests&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;MIT license&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero config&lt;/strong&gt; (3 commands)&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/crisnahine/rails-ai-context" rel="noopener noreferrer"&gt;https://github.com/crisnahine/rails-ai-context&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you’re using AI agents seriously on non-trivial Rails apps,&lt;br&gt;
file-reading alone just doesn’t cut it anymore.&lt;/p&gt;

&lt;p&gt;This gives them the same mental model &lt;strong&gt;you already have&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
