algonote(en)

There's More Than One Way To Do It

Ordinary offensive magic not available in Ruby on Rails

Comparing Rails with frameworks in other languages

There are a lot of Zoltrak in Rails

In a work called Funeral Freelens, there is a magic called Zoltraak. At first, it was recognized as a rare magic because of its power, but as a result of analysis and research, it became a magic that anyone can use and is now recognized as an ordinary offensive magic.

Similarly, Ruby on Rails framework has ordinary offensive magic because some of the things that used to be done by gems, such as active storage for file uploads and multiple database connections, are now built-in.

The libraries and frameworks authors sometimes cut out some features at a certain version because the core has grown too large. It is not always a good thing that the built-in functions are getting bigger.

However, as long as they are maintained, it is a good thing that the functions are increasing.

There are features that other language frameworks have but Rails does not. I would like to discuss how Rails can evolve more by bringing the ordinary offensive magic of other languages.

Django's affinity for machine learning

Django is a Python framework that advocates an MVT (Model, View, Template) framework rather than an MVC framework.

Django has a Django ORM, but according to the results of the Python Developers Survey, it is losing a bit to SQLAlchemy. This is different from the Ruby community, where ActiveRecord is almost the only strongest ORM.

There is one area where Ruby is losing ground to the Python community. Python is in its affinity with machine learning libraries. Although a set of libraries that use Ruby for data processing such as Red Data Tools , machine learning libraries often support only C++ or Python. In the midst of the AI boom, one rationale is to write both web and machine learning servers in Python.

On the other hand, there was a time when Django Channels complained of halting development with only one maintainer. Since Python is not web-specific, even the most popular Django framework sometimes faces a hard time for keeping up.

Django has a more modular directory structure than Rails. It has a built-in admin panel called Django Admin. Although Rails has been added basic sessions generator, Django has a user model called django.contrib.auth.models.

Personally, I think partial indexes would be nice to have in ActiveRecord too.

Object Document Mapper in Laravel

Laravel is a PHP framework that sits on top of another framework called Symfony. Laravel 9 was originally LTS, but since Symfony has been released, it is no longer LTS. This dependency has made it difficult to control releases.

There is Livewire, just like Ruby has Hotwire, which was influenced by Elixir's Phoenix LiveView. Catching up on technology trends seems relatively fast. Laravel Sail was released before Rails 7.1's automatic Dockerfile generation.

Rails has an API mode, but Rails itself is not so decomposable, while Laravel's functions are independent each other. There are many opinions here.

Some people say that the Laravel style of writing is not consistent with the presentations at PHP conferences, while others say that it is good to be able to eat a few things.

ActiveRecord is a powerful ORM, but Rails does not provide a vector DB or document DB mapper. Laravel has Laravel Scout, a full-text search wrapper, which is an excellent feature.

Laravel has FormRequest, a mechanism for authorization and validation that is separate from the controller. While you can write FormObjects using PORO (Plain Old Ruby Object) or Active Model, it is attractive to have the rails in place.

NestJS DTO

NestJS is a TypeScript framework that is not tightly coupled with ORM. It also allows you to choose whether the base framework is Express or Fastify. There are some parts where the writing style was affected by the choice.

Since there are many combinations, there may be times when you do not find the same pattern as yours when you search.

As ORM using TypeORM or Prisma is popular. Some people say that TypeORM has low type safety and low performance, while others say that Prisma has too many destructive changes and is strictly lower level than ORM.

However, both are evolving fast, so the problems you find in your search may have already been solved.

TypeORM supports tree structures and Prisma comes with a built-in SQL Client, which is a good point.

I believe that SQL type estimation is the bottleneck that prevents existing JavaScript frameworks such as Sails.js from being converted to TypeScript.

By this restriction, as is the case with Android's Room, SQL processing needs to be defined as procedure. I am looking forward to Prisma's new feature called TypedSQL.

The convention is to put a validation layer before the Controller called DTO, which is similar to Laravel's FormRequest.

Among the ActiveRecord validations, we can separate the ones that require looking at the DB value and the validations that can be processed without looking at the DB value. For the latter part, looking at it before reaching the Controller may improve the readability, or it may only complicate things if forced to do so.

I know some companies are validating with JSON Schema in Rails as well.

There's slide to generate front-end TypeScript code from Python validation definitions. Although there are differences in what can be validated by type depending on the language, all human beings think about at least once to write once the validation for the both frontend and backend by type.

CDN affinity of Next.js

Next.js is a TypeScript framework, and unlike other full-stack frameworks, it specializes in the front end of BFF (backend for frontend). It is a light framework like React with routing added.

It is attractive to have a choice of build and delivery strategies such as Client-Side Rendering (CSR), Server-Side Rendering (SSR), Static-Site Generation (SSG), and Incremental Static Regeneration (ISR).

Incremental Static Regeneration is a convenient mechanism that normally returns the cache statically and fetches and updates it from the API after a specific period of time.

The dog pile effect is known con in this pattern. If multiple servers simultaneously reacquire the cache, the servers sometimes cannot handle the sudden influx of requests. What is a dream mechanism for the front end may be a nightmare for the back end.

The term DevOps has become common. Development and operation have become integrated, but it is surprising that CDN configuration is still divided from development with infrastructure being in charge.

For example, in config/routes.rb, if there is a line that says

get 'pages/:id', :to => 'pages#show', :rendering => :isr

to can be exported to varnish (cache server) settings would be interesting future.

Go's Microservices Affinity

There are not de facto standard frameworks in the Go world. Some people say that recommended framework for Go is net/http. It is mainly used in microservices with gRPC communication.

It is attractive that it is backward-compatible and hard to break. Its philosophy is different from that of Rails development. Theres is a convention of the method to return two values, the actual response and an error object. No exception.

There is a framework for both monoliths and microservices called Service Weaver from Google, which may also give you a hint.

Microservices in Rails can consume a lot of memory when launching Rails with multiple processes. For example, if you use monorepo to manage 3 Rails and mount the 3 Rails as Rails engines on dummy Rails that are not in production, it will be recognized as a single Rails. That is really helpful for development.

If there is a gem that automatically converts GET https://service2.example.com/books/1 to get_service_2_example_com_books(1) for internal HTTP calls only during development, the transition from modular monoliths to microservices would make easy.

Actor Model of Play Framework / Spring Performance

Play Framework is a framework designed for Java/Scala and follows the Actor Model paradigm.

There has been a bit of a mess since Lightbend's Akka was no longer open source, so what was Akka 2 was migrated to Apache Pekko, a fork of Akka 3.

.NET also has Akka.NET, and while such a mechanism may be necessary in the enterprise, I think it is a use case that is the exact opposite of Rails' One Person Framework in terms of philosophy.

Spring (Boot) is popular in Java. Replacing Ruby's Mastodon with Java made it 100 times faster, and it is a point of debate whether the bottleneck is really the language in normal web services, but even though Ruby is getting faster every year, in cases where performance is needed I think it will lose to Java.

Most architecture books are Java-based. There is ArchUnit, a library similar to packwerk. There is also Spring Modulith, a modular monolith library. Java is rich in architecture-related libraries.

Ktor internal

Ktor is a framework for Kotlin. Kotlin Multiplatform makes it reasonable to use Kotlin on the server side in cases where there is more code in common with Kotlin on iOS. The languages can be aligned in proportion.

Similarly, it is rational to use Riverpod for the Dart backend in a company that uses Flutter, ASP.NET MVC for the backend in a company that develops game clients in C#, and TypeScript backend in a company that uses ReactNative (Expo).

Currently, mobile app development and game development in Ruby unfortunately loses in popularity, so we are at a disadvantage in that regard.

Kotlin has an internal, module-only public syntax, which has advantages for modular monoliths over Ruby, or rather over Rails, where the autoloader is almost compulsory.

When people talk about the advantages and disadvantages of Rails, ActiveRecord is often mentioned. However ORMs are also available in other languages and are not that unique.

Import statements are often used in PHP and Python frameworks, which are also scripting languages, so what makes Ruby on Rails is the autoloader (Zeitwerk). Rails is a framework where you don't have to write import statements.

For example, in JavaScript, there are libraries to visualize dependencies such as dependency-cruiser, etc. This reliance on autoloaders has the advantage that it can be developed with Vim/Emacs, but it is difficult to do static analysis when considering large scale modular monoliths.

The current direction of Ruby is to use external files for type definitions such as rbs. Also, the require statement, which was originally supposed to be there, can be known to some extent from constants. It would be convenient for static analysis if there is a framework to cut out the equivalent of import statements into external files for static analysis.

Rust's affinity for WebAssembly

Rust is a highly secure language, but there are still few examples of its use in web development. It is still growing. In fact, the author of the popular framework actix-web had announced the end of the project.

Rust is also used in Figma, and its real-time editing feature has improved performance, which is a bright spot in cases where performance is required.

The fact that Rust is also used in meviy and its high affinity with WebAssembly may be an advantage if you are developing CAD in a browser or trying to do something similar to native code.

Lastly: When discussing Rails, learn the behavior of other frameworks as well!

That's all. Some languages/frameworks have low resolution, so feedback is welcome if there are mistakes.

People who study English also need to have some understanding of French and German as influences. You need to be a T-type person to master something.

Ruby on Rails is often criticized because it is a popular framework, but sometimes the critics come from a limited understanding of the framework.

In order to discuss the good and bad points of Ruby on Rails, it is of course necessary to understand the behavior of several back-end frameworks to some extent. I'm happy if this article can be a good place to start.