4 ms·
> lacks strong typing for AI coding tools I've heard this criticism a few times – the fear that LLMs will be bad at Rails because there's no types – and I don'
by dceddia 2y ago
> lacks strong typing for AI coding tools
I've heard this criticism a few times – the fear that LLMs will be bad at Rails because there's no types – and I don't think it's accurate.
At least in my experience (using the Windsurf IDE with Claude 3.5 Sonnet) LLMs do a very good job in a Rails codebase for stuff like "I want to create a new page for listing Widgets, and a Create page for those Widgets. And then add pagination.". I've been able to spin up whole new entities with a model/view/controller and database migration and tests, styled with tailwind.
I think the reason strong types don't matter as much as we might assume is because Rails has very strong conventions. Routing lives in routes.rb, controllers go under app/controllers, most controllers or models will look very similar to other ones, etc.
Type information is something that has to be presented to the LLM at runtime for it to be accurate, but convention-over-configuration is stuff that it will have picked up in training data across thousands of Rails apps that look very similar.
On top of that, the core Rails stuff hasn't drastically changed over time, so there's lots of still-accurate StackOverflow questions to train on. (as opposed to something like Next.js which had a huge upheaval over app router vs pages router, and the confusion that would cause in training data).
In my opinion the future of LLM-aided Rails development seems pretty bright.
- philip1209 2y agoI've noticed that, in agent workflows like Cursor, they're able to use built-in type checkers to correct errors. With Ruby, it doesn't have as much information, so it has to rely on testing or linters for feedback.
- dceddia 2y agoI haven't seen it run into a ton of issues like this when it can see all of the files, but I did hit issues where it would make guesses about how e.g. the Stripe gem's API worked and they'd be wrong. Overall with Rails though, testing has always been pretty important partly because of the lack of types. I have noticed Windsurf is pretty good at taking a controller or model and writing tests for it though!
- freedomben 2y agoYou make some good points, but I think as AI continues progressing down the road of "reasoning", any data points that allow it to reason more will be helpful, including (and maybe especially) types. AI could definitely reason about rails too, and perhaps it will quickly get really good at that (especially if it "understands" the rails source code) but it's hard to think of a situation in which less data is more useful than more data
- dceddia 2y agoI think types can help, but I don't think they're "strong" enough to overrule training data. I just ran into an example of this trying to get it (Windsurf + Claude) to "rewrite this Objective C into Rust using the objc2 crate". It turns out objc2 made some changes and deprecated a bunch of stuff. It's not figuring stuff out from base principles and reading the types to write this code, it's just going off of all the examples it was trained on that used the old APIs, so there's lots of errors and incorrect types being passed around. Hopefully it'll keep getting better.
- sergiotapia 2y agoIn Elixir land we have Instructor. It hits AI endpoints cleanly, and then validates the returned JSON using Ecto Changesets. Very powerful, clean abstraction. Love it! https://hexdocs.pm/instructor/Instructor.html https://hexdocs.pm/instructor/Instructor.html Someone in Rails land could build similar and voila.
- Kerrick 2y agoSee also: https://gist.github.com/peterc/214aab5c6d783563acbc2a9425e5e866 https://gist.github.com/peterc/214aab5c6d783563acbc2a9425e5e...
- e12e 2y ago> At least in my experience (using the Windsurf IDE with Claude 3.5 Sonnet) LLMs do a very good job in a Rails codebase for stuff like "I want to create a new page for listing Widgets, and a Create page for those Widgets. And then add pagination.". I've been able to spin up whole new entities with a model/view/controller and database migration and tests, styled with tailwind. Does it suggest using rails generators for this - and/or does it give you idiomatic code?
- dceddia 2y agoThe last time I tried this it created idiomatic code from scratch. I prompted it in phases though, and I suspect if I had asked it for more at once it might've used a generator.
- snickell 2y agoI suspect long-term LLMs spell the end of typed language popularity in most application programming contexts. I agree with The Grug Brained Developer (https://grugbrain.dev/ https://grugbrain.dev/) that “type systems most value when grug hit dot on keyboard and list of things grug can do pop up magic. this 90% of value of type system or more to grug”. This already is being heavily replaced by LLMs (e.g. copilot) in many people’s workflows. Co-pilot’s suggestions are already mostly higher level, and more useful, than the static typing auto-complete. I believe the quality-of-autocomplete gap between typed and untyped languages has already largely converged in 2025. Co-pilot today writing TypeScript just doesn’t produce overwelmingly better auto-complete results than JavaScript. Compare with 4 years ago, where Javascript auto-complete was trash compared with TS. And even then, people argued the merits of untyped: all else being equal, less is more. What happens when “all else” IS equal? ;-) Currently, static typing can help the LLM generate its code properly, so it has value in helping the LLM itself. But, once the LLM can basically hold your whole codebase in its context, I don’t see much use for static typing in implementing the “hit dot on keyboard, see list of things you can do” advantage. Essentially, the same way type inference / auto lets languages skip repetitive specification typing, by holding your whole codebase in memory the LLM can mostly infer the type of everything simply by how it is called/used. LLMs take type inference to the next level, to the degree that the type barely needs to be specified to know “press ., see what you can do” I rarely use the static typing type of auto-completion when programming now, almost everything I accept is a higher level LLM suggestion. Even if that’s not true for you today, it might be tomorrow. Is the remaining 10% of “formal correctness” worth the extra volume of characters on the screen? I suspect Rust will do well into the distant LLM future (used in contexts where formal correctness is relatively important, say kernels), and I suspect TypeScript will decrease in popularity as a result of LLMs.
- Tainnor 2y ago> Is the remaining 10% of “formal correctness” worth the extra volume of characters on the screen? Yes, if only just for the ease of large-scale refactorings. And "extra volume of characters" is very limited if you use a modern language. In Haskell you could even not write a single type annotation in all of your code, although that's not recommended. I doubt most people who like static types only do so because of autocomplete.
- janee 2y agoSo we have an LLM code scaffold repo we use in a large (2m loc) production Rails codebase and it works amazingly well. Rails and especially Ruby lends itself to describing business logic as part of source code closer to natural language than a lot of typed languages imo and that synergizes really well with a lot of different models and neat LLM uses for code creation and maintenance.
- dceddia 2y agoInteresting! What sort of stuff goes in the scaffold repo? Like examples of common patterns? Definitely agree I think Ruby's closeness to natural language is a big win, especially with the culture of naming methods in self-explanatory ways. Maybe even moreso than in most other languages. Swift and Objective C come to mind as maybe also being very good for LLMs, with their very long method names.
- janee 2y agoit's fairly bespoke, but some examples: ETL pipelines, we catalogue and link our custom transformers to bodies of text that describes business cases for it with some examples, you can then describe your ETL problem in text and it will scaffold out a pipeline for you. Fullstack scaffolds that go from models to UI screen, we have like a set of standard components and how they interact and communicate through GraphQL to our monolith (e.g. server side pagination, miller column grouping, sorting, filtering, PDF export, etc. etc.). So if you make a new model it will scaffold the CRUD fully for you all the way to the UI (it get's some stuff wrong but it's still a massive time save for us). Patterns for various admin controls (we use active admin, so this thing will scaffold AA resources how we want). Refactor recipes for certain things we've deprecated or improved. We generally don't migrate everything at once to a new pattern, instead we make "recipes" that describe the new pattern and point it to an example, then run it as we get to that module or lib for new work. There are more, but these are some off the top of my head. I think a really big aspect of this though is the integration of our scaffolds and recipes in Cursor. We keep these scaffold documents in markdown files that are loaded as cursor notepads which reference to real source code. So we sort of rely heavily on the source code describing itself, the recipe or pattern or scaffold just provides a bit of extra context on different usage patterns and links the different pieces or example together. You can think of it as giving an LLM "pro tips" around how things are done in each team and repo which allows for rapid scaffold creation. A lof of this you can do with code generators and good documentation, but we've found this usage of Cursor notepads for scaffolds and architecture is less labour intensive way to keep it up to date and to evolve a big code base in a consistent manner. --- Edit: something to add, this isn't a crutch, we require our devs to fully understand these patterns. We use it as a tool for consistency, for rapid scaffold creation and of course for speeding up things we haven't gotten around to streamlining (like repetitive bloat)
- Glyptodon 2y agoI've found LLMs are pretty good at generating basic code for everything except the specs/tests when it comes to Rails. Lot of my work lately has been like 4x more time w/ specs/tests than actually creating the application code because LLM just isn't cutting it for that part.