eyecatch

Try Rust web framework - Loco

Posted on 2023/12/10
# Technology

Abunt Loco

The Luco being developed in Rust, is similar to Ruby on Rails, and currently progressing up to Stage 3 out of the five stages. It is designed for small application and individual developers, aiming to enable a single person to develop the application with many build in supporting tools such as authentication, authorization, tasks, and mailing.

It incorporates the ease of development specific to Ruby on Rails while leveraging Rust's powerful static typing and performance. I have been interested in this project for a while because I like both Rust and Ruby on Rails.

Although it is still in the middle of development at this point, there was a significant announcement, so I will try it out, explore its contents, and see what it's all about.

Installation

To make Loco app, need to install loco-cli.

cargo install loco-cli

To make loco app, run below command.
We have three options at the first.

loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas app (with DB and user auth)

// App 3通りの選択肢がありました。
// 今回は Saas app を選択
- Saas app (with DB and user auth)
- Stateless service (minimal, no db)
- Stateless HTML (minimal, no db)

Run postgres DB on Docker.

$ docker run -d -p 5432:5432 -e POSTGRES_USER=loco -e POSTGRES_DB=loco_app -e POSTGRES_PASSWORD="loco" postgres:15.3-alpine

To run a server。

cargo loco start

The API server run on port 3000 if you can see terminal like image below.

                      ▄     ▀                     
                                 ▀  ▄             
                  ▄       ▀     ▄  ▄ ▄▀           
                                    ▄ ▀▄▄         
                        ▄     ▀    ▀  ▀▄▀█▄       
                                          ▀█▄     
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█    
 ██████  █████   ███ █████   ███ █████   ███ ▀█   
 ██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄  
 ██████  █████   ███ █████       █████   ███ ████▄
 ██████  █████   ███ █████   ▄▄▄ █████   ███ █████
 ██████  █████   ███  ████   ███ █████   ███ ████▀
   ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀  
       ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀    
                https://loco.rs

environment: development
   database: automigrate
     logger: debug
      modes: server

listening on port 3000

Directories

.
├── config // Config files for each environments.
├── examples // Demo app will be here?
├── migration // sea-orm based migration files.
├── src
│   ├── bin // top main app.
│   ├── controllers // routes and handlers are in same file.
│   ├── fixtures // seed data is stored?
│   ├── mailers // There are function for sending mails.
│   ├── models // Like ActiveRecord. function are implemented into entities model here.
│   │   └── _entities // seaORM auto generates model files.
│   ├── tasks // Task files.
│   ├── views // Response for views, such as LoginResponse.
│   └── workers // now there is payment report as example.
└── tests // Test files
    ├── cmd
    ├── models
    │   └── snapshots
    ├── requests
    │   └── snapshots
    └── tasks

Since it is still in the midst of development, it is structured in a simple manner.
You can see the influence of Rails. Currently, the service layer and handler are defined together with the route, but the structure is expected to change in the future.

Models access to DB like ActiveRecord

As an example, let see find_by_email function in models > users.

impl super::_entities::users::Model {
    /// finds a user by the provided email
    ///
    /// # Errors
    ///
    /// When could not find user by the given token or DB query error
    pub async fn find_by_email(db: &DatabaseConnection, email: &str) -> ModelResult<Self> {
        let user = users::Entity::find()
            .filter(users::Column::Email.eq(email))
            .one(db)
            .await?;
        user.ok_or_else(|| ModelError::EntityNotFound)
    }
    ...
}

seaORM generates _entities::users so implement functions and logic in models.
It consider about Fat Model like Ruby on Rails, we will see how Loco handle about weak point of Ruby on Rails.
Custom Errors are defined. The folder structure are build well.

#[derive(Debug, Validate, Deserialize)]
pub struct ModelValidator {
    #[validate(length(min = 2, message = "Name must be at least 2 characters long."))]
    pub name: String,
    #[validate(custom = "validation::is_valid_email")]
    pub email: String,
}

impl From<&ActiveModel> for ModelValidator {
    fn from(value: &ActiveModel) -> Self {
        Self {
            name: value.name.as_ref().to_string(),
            email: value.email.as_ref().to_string(),
        }
    }
}

Furthermore before_save , Validation and so on, are implemented already. Validator library is used for validations so many people who use Rust may already familiar with it.

Closing

The structure seems relatively easy to understand, even for those who haven't worked with Rails. As it is still in development, still a single file contains many roles such as handler and routes, but there is an intention to separate them, as indicated by the implementation. Similar to Ruby on Rails being object-oriented programming (OOP), Loco appears to follow a philosophy close to OOP, adding logic to models. People who enjoy OOP might find it appealing.

However, considering Loco's concept as "The one-person framework," it doesn't seem geared towards large projects. Nonetheless, it appears well-suited for small to medium-sized services or individual development.

One point of interest is how Loco will address opinions like the "Fat Model" debate seen in Ruby on Rails. It will be intriguing to see the approach taken in the future.

Features like the console functionality present in Ruby on Rails are eagerly desired—very much so.