Systematically migrating projects from Rails - Ideas


#1

Hey everyone! Thanks for your awesome work on this framework. I have an idea that has been floating around in my head for quite some time, and I’d like to get some experienced Hanami devs opinions on it.

As a Rails developer, I’d love to move to Hanami, so I can benefit from its organization, structure, etc. However, I have a few Rails apps that I still need to support and maintain. I’m sure a huge amount of Rails developers also feel the pain of the Rails monolith, but are too scared to try to migrate to something else.

Since Rails and Hanami both share quite a few things that would seem to make switching from one to another easier, it would make sense at a certain level to see how that could possibly happen. I definitely know that this is not as simple as it seems (nothing ever is), but I think there might be a ‘systematic’ way to migrate an existing code base from Rails to Hanami. And of course, if something is systematic, it can possibly be scripted. :grin: At the least, I think some interesting discussion could be had.

Please note the bolded words above. I realize this would not be easy or trivial. I realize that static code analysis is not super easy in a dynamic language.

The Idea

Since we as a community have a lot of Ruby code that makes us money, we don’t want to move to other languages like Elixir, Crystal, etc,. We just want a better structure and well-thoughout design patterns for our existing code.

What if we could design a script that would automatically convert/migrate our existing Rails code over to a Hanami structure? It wouldn’t do 100% of the work, but could do a large amount, and we as developers can finish it up by running tests and fixing found issues.

What a tool could look like

$ rails2hanami migrate controllers myapp-rails myapp-hanami
# Looking for app/controllers...
# Found 10 controller files (suffixed with _controller.rb)
# Moving UsersController (namespace Users) to apps/web/controllers/users directory and splitting up actions
# Created 5 actions for Web::Controllers::Users (new, create, edit, update, destroy).
# Copied 4 before_filters, 3 after_filters, 2 around_filters to apps/web/controllers/users/filters.rb.
# Included Filters module in Users:: action.
# Finished UsersController.
# Moving PostCommentsController (namespace PostComments) to apps/web/controllers/post_comments/
# ...

Is this interesting to anyone?

If so, please let me know. It would be helpful if you could respond with answers to the following questions:

  • Would you use this if it was built?
  • Would you be willing to use it even if it only did 90% of the work? 80%? 50%?
  • Would you be willing to help design/implement it?

Who could use this?

First, why do you want to use this?

  • Do you want to leverage your existing Ruby code, but just leave Rails?
  • Do you want to move toward a better organized structure because you have a monolith that is getting harder and harder to understand?

If you answered yes to either of the above questions, then this could work for you.

Unfortunately, I would guess that the scope of something like this is limited to ‘medium’ to low complexity Rails apps. If you have a non-standard Rails directory structure, then this is not for you. If you have multiple engines, or a microservices architecture, then this is probably not for you.

However, if you have a somewhat well-designed / convention based monolith Rails app, with well tested code, then this could make your life a lot easier.

Is this possible to any degree?

Yes, of course, to some degree. Static code analysis of ‘typical’ Rails code is made easier because of Rails conventions. I’ve used this Ruby AST parser before on Rails code and could probably guess that over 60% of my controllers fall into the standard Rails conventions.

If someone has more experience with this, please chime in. I’ve only spent a few days of work on a similar idea, which I scrapped. But it did get about 30-40% of the way there.

What makes this easier

Here’s what I think would be the parts of a typical Rails app that would make it easy to design a system to make a migration possible, and are also somewhat easily analyzed by a static code analysis.

  • Rails apps often have an acceptable test coverage. (If you don’t have acceptable integration test coverage, then of course it’s a terrible idea to try to move all of your code around.)
  • We have a standard folder structure. We know views are in app/views, controllers are in app/controllers, models are in app/models, initializers are in config/initializers. Routes are in config/routes.rb. All of these can be more or less moved to the correct place in Hanami.
  • We have quite a few conventions for how code is laid out
    • Controllers
      • Ruby classes in the app/controllers folder that have the word controller in the class name or file name are ‘definitely’ controllers.
      • Public instance methods in those classes are almost definitely ‘actions’.
      • private methods in the folder that have a corresponding before/after/around_action :method_name class level call can be easily recognized
    • ModelsRuby classes in the app/models folder that inherit from ActiveRecord::Base or ApplicationModel are ActiveRecord models.
    • Views (Templates)
      • templates that reference @variables are almost definitely referencing variables that were set in the controller’s action method or a before_filter, so we know that this needs to be exposed to the view.

And so on…

Questions to consider

  1. Has something like this already been made?
  2. If not a script or tool, is there a definitive guide for migrating?
  3. Are people in the Hanami community genuinely interested in migrating existing Rails apps, or are most Hanami users just doing greenfield projects?
  4. Would this really be worth the trouble? Is doing it by hand not so hard?
  5. What is an acceptable amount of work for a script to do? Would people be happy with 50% of the tedious work being done for them, or is it closer to 90+% for it to be a useful product?

Thanks for reading :smile:


#2

@yjukaku Thanks for the extended explanation of your proposal.

Please proceed if you think it’s possible. It seems a quite complex task. Please keep us updated with the progress. :wink: