mikesax

mikesax

I have a fairly old Rails project that is non-trivial but also not a beast, and I would like to convert it to a modern Elixir app, retaining the database structure and (at this point) the existing UI. LiveView would be nice but it would be perfectly fine for now to use regular controllers.

Since AI is pretty good at working from a spec, I’d like to try and use one of the major AI tools (Claude, Codex, Jules, …) to do this. It seems that the key would be to do this step-by-step and keep the context as focused as possible. For example, start with the database migrations, relationships, then validation, model operations, etc.

Has anyone done this? Any gotchas or recommendations?

Thank you!

Mike

Showing Posts 1 to 10

AstonJ

AstonJ

This is a cool idea! Even something that can generate migrations or the initial files from a Rails schema could be really handy and make a port that little bit easier.

pupdogg

pupdogg

Currently knee-deep in moving a Rails 2.3 app (on MySQL) over to Phoenix with LiveView + PostgreSQL. This app has zero specs. Nada. Zilch. But it’s been quietly doing its thing for the client for the last 15 years without many hiccups. So, I’m basically doing surgery on a patient that’s been healthy for a decade and a half. The reason for the operation is that it’s getting harder to keep the old JS libraries like Prototype limping along, and the customer recently took a hit when they were forced to migrate from MySQL 5.7 to MySQL 8. That alone required a big lift to move Rails 2.3 over to Rails 2.3 LTS, and they don’t want to go through another “fire drill” like that ever again.

Didn’t want to just throw the entire codebase into Claude or ChatGPT and pray, so I’ve been breaking the migration down into chunks:

  1. Dumped the MySQL DB schema → fed it to AI to get a Postgres version, plus suggestions for cleaner field types and future-proofing.
  2. Logged all the field type changes, then used draw.io to map out how the tables actually connect so I could decide which models to tackle first.
  3. Spun up a barebones Phoenix + LiveView app and scaffolded those models in priority order.
  4. Right now: pulling in the old business logic one model at a time, while getting AI to crank out tests for each bit as I go. This part is equal parts archaeology and translation work. Finding ancient Rails patterns and figuring out their shiny new Elixir equivalents.
  5. Next up will be staging for the client’s management to kick the tires.
  6. Then a tiny rollout to 1–2 locations for a couple months of feedback.
  7. Expand to ~25 locations for another few months of tweaks.
  8. Finally, the big switch for all 100+ locations.

One extra wrinkle: most of the production data from MySQL ultimately ends up in ClickHouse for warehousing. As I launch these new locations, I plan on setting up triggers in Postgres so it will automatically dump the exact same data format for the warehouse into a temp table that I sync daily. This way, the downstream analytics won’t even notice the migration happened. Once the rollout is solid, the next big mountain will be refining and transforming that warehouse data.

mikesax

mikesax OP

This is super interesting, thank you! Did you try anything that simply didn’t work (like maybe converting the relationships?) and when was this all happening (ie: how good was the AI compared to today).

dimitarvp

dimitarvp

While you are at it, I strongly recommend skipping the more raw Ecto stuff and just use Ash. You declaratively describe stuff and it can even generate the migrations for you, though it can do much, much more than that. It’s a joy to use and allows you to compartmentalize stuff a la Phoenix contexts but IMO better.

pupdogg

pupdogg

First of all, I don’t consider myself an expert in Elixir, but as an intermediate Ruby dev, I know enough about programming in general to wiggle my way around. I purchased Pragmatic Studio’s Elixir OTP and Full-Stack Phoenix courses last year and have been using them as my foundation to tackle this challenge. I’ve been at this for the past 3 months, so everything is from a fairly recent experience. Overall, Claude is my go-to…specifically Sonnet 3.7, which seems to perform better overall. As for snags, you can’t expect AI to take OOP patterns and automagically convert them into functional and/or concurrent counterparts. I’ve noticed that this part definitely requires some back-and-forth with the AI to get right.

pupdogg

pupdogg

This sounds very interesting. I’ll have to take a look at Ash. Thanks for the tip :+1:

pupdogg

pupdogg

Thanks for pointing me to Ash…boy, it’s hell of a framework…mind blown!!! I’m working on a new new point-of-sale project and this will most definitely come in handy.

dimitarvp

dimitarvp

I was a skeptic for a long time but as it usually happens in life, I was forced to use it to appreciate it. I grumbled about it, of course, like every self-respecting aging techie, but came to appreciate it a lot.

Best feature is being able to describe one resource’s data model once and then reuse that for JSON API, GraphQL, storage backends like PostgreSQL / sqlite3, and others. Also before_action / after_action, notifiers, PubSub… The authors did an amazing job.

Feel free to ask about how to do this and that. I am not an expert by any stretch but the parts that I learned I know pretty well. Busy as all hell too but I stop by in the forum 1-2 times a day.

brendon9x

brendon9x

So I have wondered about the exact same thing. I haven’t done it yet, but I have had success upgrading an Elixir app. The upgrade included:

  • Phoenix 1.4 to 1.8 with no shims or backwards compatibility tricks, including
    • EEX → HEEX
    • LEEX → HEEX
    • View → HTML
    • Routes → ~p()
  • LiveView 0.16 to 1.1 including
    • Move to new components.ex
    • Streams
    • Async assign
  • Bootstrap 4 → Tailwind + DaisyUI
  • Webpack → esbuild

One key thing that didn’t work was incremental upgrading. I first tried to take Phoenix and Liveview, feed in the CHANGELOG and UPGRADING guides for each version bump and work my way to 1.8/1.1 while going fully idiomatic for each version. I made it through a few of tech changes listed above, but got in a hot mess half way through trying to get the exact magic mix of packages right for each era of the upgrades. I eventually decided that a single-jump rewrite was going to take less time (and it did).

So I threw all the progress away from above, reverted back a clean old working branch. Then I did a mix phx.new in a parallel directory. I was using Warp which was a surprising capable AI codegen tool (and under appreciated). I mounted both the existing app and the newly generated app and described how I wanted to upgrade the one into a modern skeleton. Crucially, what worked for me, was keeping an up-to-date UPGRADE.md file in the new folder. It did a fantastic job coming up with a high level plan which was basically to start with copying the migrations and the business logic over and then building the interface up route by route.

As it started each route, it did a great job of understanding the core idea of each live/dead view it was replacing. But also, I think the Ecto Schemas were likely the most important source of truth it needed to create the views. I would get it then to add detail to each part of the high level plan as it went through each section making a very detailed plan in the end.

It took about 10 hours to migrate something that took me 3 months to write. The entire _web folder and all tests are from scratch. This is approach I’d take with migrating a Rails app too. If it was sufficiently complex, I may add a few extra “understanding” stages before even creating the plan file.

On process, I am a huge fan of this “create a markdown plan file as you go” approach. I suspect Claude Code, Cursor and friends are basically doing a similar thing under the hood now, but I like being able to carry my plan across sessions, LLMs and agents. I’ve also found that using Opus for planning is worth it, but Sonnet good enough for implementing the plan.

venkatd

venkatd

One thing I might recommend before doing a full conversion - you may want to first have AI make your rails app more convertible. This would mean:

  • Add more documentation to the Rails app
  • Adding more test coverage / integration tests to the Rails app

That way, the conversion process will have additional context on the behavior of the Rails app and the AI can also be instructed to port the integration tests over to Phoenix.

Hope that helps!

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 91898 914
New
AstonJ
The obligatory hello world thread! Who are you and where are you from? :stuck_out_tongue:
4616 55835 594
New
byu
@chrismccord : I just saw the Extract AGENTS.md from Phoenix.new into phx.new generator commit to the phoenix project. My initial shotgu...
New
arcanemachine
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
matt-savvy
Is there a word for the ~> symbol used in Version strings? Do you also just call it a Squiggle Arrow™ ?!
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews