<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilya N. Zykin</title>
    <description>The latest articles on DEV Community by Ilya N. Zykin (@the_teacher).</description>
    <link>https://dev.to/the_teacher</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1068333%2F689ab77a-a7ef-4354-8ceb-bc7ef91560e2.jpeg</url>
      <title>DEV Community: Ilya N. Zykin</title>
      <link>https://dev.to/the_teacher</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/the_teacher"/>
    <language>en</language>
    <item>
      <title>How Makefile Helps Rails Developers</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Wed, 08 Oct 2025 07:53:15 +0000</pubDate>
      <link>https://dev.to/the_teacher/how-makefile-helps-rails-developers-3mb3</link>
      <guid>https://dev.to/the_teacher/how-makefile-helps-rails-developers-3mb3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Several years ago, I needed a quick playground for launching &lt;strong&gt;Rails&lt;/strong&gt; applications for new projects and experiments. I also create video lectures and masterclasses on &lt;strong&gt;Rails&lt;/strong&gt;, and I needed a project where my program attendees could practice their skills.&lt;/p&gt;

&lt;p&gt;This is how the &lt;strong&gt;&lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;RailsStart&lt;/a&gt;&lt;/strong&gt; project was created, which allows launching &lt;strong&gt;Rails&lt;/strong&gt; applications quickly, almost instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main goal of the project&lt;/strong&gt; - to enable running &lt;strong&gt;Rails&lt;/strong&gt; on any operating system with literally one command.&lt;/p&gt;

&lt;p&gt;In this article, I will tell you about the importance of &lt;code&gt;Makefile&lt;/code&gt; for implementing my project. Its architecture is based on the elegant use of &lt;code&gt;Makefile&lt;/code&gt; - a tool that transforms complex &lt;strong&gt;Docker&lt;/strong&gt; and &lt;strong&gt;Rails&lt;/strong&gt; commands into simple and understandable calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Make and Makefile?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Make&lt;/strong&gt; is a build automation utility that manages the compilation and build process of software. It uses a file called &lt;strong&gt;Makefile&lt;/strong&gt;, which describes the rules and dependencies for building a project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Makefile&lt;/code&gt;&lt;/strong&gt; is a text file containing a set of instructions for the &lt;strong&gt;Make&lt;/strong&gt; utility.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Makefile&lt;/code&gt; is commonly used in &lt;strong&gt;C/C++&lt;/strong&gt; projects for compilation, in system administration for task automation, in &lt;strong&gt;DevOps&lt;/strong&gt; for deployment management, and in various projects for standardizing development commands.&lt;/p&gt;

&lt;p&gt;In my project, &lt;strong&gt;Make&lt;/strong&gt; and &lt;code&gt;Makefile&lt;/code&gt; are of great importance. These tools allow me to automate project setup and &lt;strong&gt;Rails&lt;/strong&gt; application launch.&lt;/p&gt;

&lt;p&gt;Thanks to the simplicity of &lt;strong&gt;Make&lt;/strong&gt;, launching a &lt;strong&gt;Rails&lt;/strong&gt; application in my project is done simply, elegantly, and with literally one command.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you need to run &lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;Rails Start&lt;/a&gt;?
&lt;/h2&gt;

&lt;p&gt;To run &lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;Rails Start&lt;/a&gt;, you need only three tools familiar to any developer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git&lt;/strong&gt; - to get the project from &lt;strong&gt;GitHub&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make&lt;/strong&gt; - to run the automatic installation process&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; - to run the application in a container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these tools are available on your operating system, you can consider that the &lt;strong&gt;Rails&lt;/strong&gt; application will be installed in less than 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do I use &lt;strong&gt;Make&lt;/strong&gt; instead of &lt;strong&gt;Ruby&lt;/strong&gt; scripts?
&lt;/h2&gt;

&lt;p&gt;The first version of the project relied on automation and launch scripts based on &lt;strong&gt;Ruby&lt;/strong&gt; technologies.&lt;/p&gt;

&lt;p&gt;However, to make the process universal for host machines where &lt;strong&gt;Ruby&lt;/strong&gt; might not be installed, I switched to using the popular &lt;strong&gt;Make&lt;/strong&gt;, which can be used both on the host machine and in a container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of Make over Ruby scripts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Universality&lt;/strong&gt; - &lt;strong&gt;Make&lt;/strong&gt; is available on virtually all &lt;strong&gt;Unix&lt;/strong&gt; systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independence&lt;/strong&gt; - does not require &lt;strong&gt;Ruby&lt;/strong&gt; installation on the host system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt; - clear syntax for command automation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardness&lt;/strong&gt; - a familiar tool for developers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two-Level &lt;code&gt;Makefiles&lt;/code&gt; Architecture
&lt;/h2&gt;

&lt;p&gt;The key feature of &lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;RailsStart&lt;/a&gt; lies in the &lt;strong&gt;two-level &lt;code&gt;Makefiles&lt;/code&gt; system&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;RailsStart&lt;/a&gt; project uses 2 levels of &lt;code&gt;Makefiles&lt;/code&gt;. One level is designed for use at the host system level (the computer you work on), the second level of &lt;code&gt;Makefiles&lt;/code&gt; is designed for use inside &lt;strong&gt;Docker&lt;/strong&gt; containers.&lt;/p&gt;

&lt;p&gt;I try to adhere to unified and consistent command names so that identical commands can be run at different levels using approximately identical &lt;strong&gt;Make&lt;/strong&gt; commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Host Level (Project)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Location:&lt;/strong&gt; &lt;code&gt;/Makefiles/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This level is responsible for managing &lt;strong&gt;Docker&lt;/strong&gt; containers and orchestrating the entire project. Host-level commands automatically delegate execution to the appropriate containers, providing a uniform interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Simple launch of the entire project
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;rails-start&lt;/span&gt;

&lt;span class="c"&gt;# Container management
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;start&lt;/span&gt;    &lt;span class="c"&gt;# Start containers
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;stop&lt;/span&gt;     &lt;span class="c"&gt;# Stop containers
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;status&lt;/span&gt;   &lt;span class="c"&gt;# Container status
&lt;/span&gt;
&lt;span class="c"&gt;# Delegating Rails commands to container
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;rails-console&lt;/span&gt;     &lt;span class="c"&gt;# Open Rails console
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;rails-db-migrate&lt;/span&gt;  &lt;span class="c"&gt;# Run migrations
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;rails-server&lt;/span&gt;      &lt;span class="c"&gt;# Start Rails server
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Main functions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose&lt;/strong&gt; management&lt;/li&gt;
&lt;li&gt;Project environment setup&lt;/li&gt;
&lt;li&gt;Command delegation to containers&lt;/li&gt;
&lt;li&gt;File structure organization&lt;/li&gt;
&lt;li&gt;Unified interface for all operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Container Level
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Location:&lt;/strong&gt; &lt;code&gt;/__RailsApp__/Makefiles/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This level contains commands that are executed directly inside the &lt;strong&gt;Rails&lt;/strong&gt; container. Commands have similar names to host commands but are executed in the container context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Commands inside container
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;setup&lt;/span&gt;      &lt;span class="c"&gt;# Rails application setup
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;console&lt;/span&gt;    &lt;span class="c"&gt;# Rails console
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;db-migrate&lt;/span&gt; &lt;span class="c"&gt;# Database migrations
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;server&lt;/span&gt;     &lt;span class="c"&gt;# Start Rails server
&lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;bundle&lt;/span&gt;     &lt;span class="c"&gt;# Install gems
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Main functions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rails&lt;/strong&gt;-specific commands&lt;/li&gt;
&lt;li&gt;Database management&lt;/li&gt;
&lt;li&gt;Dependency management (&lt;strong&gt;bundler&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Generators and testing&lt;/li&gt;
&lt;li&gt;Direct execution in &lt;strong&gt;Rails&lt;/strong&gt; application context&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Modular Structure
&lt;/h2&gt;

&lt;p&gt;Each level is organized with sets of Makefile files with specific purposes for better structure and maintenance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails-start/
├── Makefiles/                   # Host level
│   ├── 100_Project.mk           # Docker and project management
│   ├── 200_Rails.mk             # Rails command delegation
│   ├── 300_Rails-Production.mk  # Production environment
│   └── 400_env.mk               # Environment variables management
│
└── __RailsApp__/
    └── Makefiles/               # Container level
        ├── 100_Project.mk       # Common container commands
        ├── 200_Rails.mk         # Rails development
        └── 300_Production.mk    # Production commands
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Host level:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;100_Project.mk&lt;/code&gt; - Docker and project management&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;200_Rails.mk&lt;/code&gt; - Rails command delegation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;300_Rails-Production.mk&lt;/code&gt; - Production environment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;400_env.mk&lt;/code&gt; - Environment variables management&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Container level:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;100_Project.mk&lt;/code&gt; - Common container commands&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;200_Rails.mk&lt;/code&gt; - Rails development&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;300_Production.mk&lt;/code&gt; - Production commands&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advantages of This Approach
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Command Uniformity at Different Levels&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Thanks to unified command names, developers can use similar commands both on the host and inside the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On host&lt;/span&gt;
make rails-console     &lt;span class="c"&gt;# Delegates to container&lt;/span&gt;
make rails-db-migrate  &lt;span class="c"&gt;# Delegates to container&lt;/span&gt;

&lt;span class="c"&gt;# Inside container (after make rails-bash)&lt;/span&gt;
make console           &lt;span class="c"&gt;# Executes directly&lt;/span&gt;
make db-migrate        &lt;span class="c"&gt;# Executes directly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Ease of Use&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Instead of complex command:&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker/docker-compose.yml &lt;span class="nb"&gt;exec &lt;/span&gt;rails_app bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails db:migrate

&lt;span class="c"&gt;# Simply:&lt;/span&gt;
make rails-db-migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Command Unification Across Operating Systems&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Whether you work on &lt;strong&gt;macOS&lt;/strong&gt;, &lt;strong&gt;Linux&lt;/strong&gt;, or &lt;strong&gt;Windows&lt;/strong&gt; (via &lt;strong&gt;WSL&lt;/strong&gt;), the commands remain the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Self-Documentation&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make &lt;span class="nb"&gt;help&lt;/span&gt;                   &lt;span class="c"&gt;# General help&lt;/span&gt;
make rails-help             &lt;span class="c"&gt;# Rails commands&lt;/span&gt;
make project-help           &lt;span class="c"&gt;# Project management&lt;/span&gt;
make rails-production-help  &lt;span class="c"&gt;# Production commands&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. &lt;strong&gt;Transparent Command Delegation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Host commands are automatically delegated to containers, maintaining interface uniformity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# On host (Makefiles/200_Rails.mk)
&lt;/span&gt;&lt;span class="nl"&gt;rails-console&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;COMPOSE_FILE&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;rails_app make console

&lt;span class="nl"&gt;rails-db-migrate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;COMPOSE_FILE&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;rails_app make db-migrate

&lt;span class="c"&gt;# In container (__RailsApp__/Makefiles/200_Rails.mk)
&lt;/span&gt;&lt;span class="nl"&gt;console&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails console

&lt;span class="nl"&gt;db-migrate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture allows developers not to think about where exactly the command is executed - the system automatically chooses the right context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Quick project start:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/the-teacher/rails-start.git
&lt;span class="nb"&gt;cd &lt;/span&gt;rails-start
make rails-start  &lt;span class="c"&gt;# All ready!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Daily development:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make rails-console     &lt;span class="c"&gt;# Open Rails console&lt;/span&gt;
make rails-db-migrate  &lt;span class="c"&gt;# Run migrations&lt;/span&gt;
make rails-logs        &lt;span class="c"&gt;# View logs&lt;/span&gt;
make rails-status      &lt;span class="c"&gt;# Check processes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Database operations:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make rails-db-create   &lt;span class="c"&gt;# Create database&lt;/span&gt;
make rails-db-seed     &lt;span class="c"&gt;# Seed with data&lt;/span&gt;
make rails-db-reset    &lt;span class="c"&gt;# Full reset (with warning)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generators and testing:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make rails-bash                             &lt;span class="c"&gt;# Enter container&lt;/span&gt;
make generate-model &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;User               &lt;span class="c"&gt;# Create model&lt;/span&gt;
make generate-controller &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Users         &lt;span class="c"&gt;# Create controller&lt;/span&gt;
make &lt;span class="nb"&gt;test&lt;/span&gt;                                   &lt;span class="c"&gt;# Run tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Makefile&lt;/code&gt; is not commonly found in &lt;strong&gt;Rails&lt;/strong&gt; projects, and this technology is not very widespread for working with &lt;strong&gt;Rails&lt;/strong&gt; applications. However, the &lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;RailsStart&lt;/a&gt; project shows an example of an effective and elegant solution for running &lt;strong&gt;Rails&lt;/strong&gt; on any operating system.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Makefile&lt;/code&gt; in the &lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;RailsStart&lt;/a&gt; project doesn't just simplify commands - it creates a &lt;strong&gt;unified management interface&lt;/strong&gt; for the entire &lt;strong&gt;Rails&lt;/strong&gt; application lifecycle.&lt;/p&gt;

&lt;p&gt;The two-level architecture provides clear separation of responsibilities between infrastructure management (host) and application development (container).&lt;/p&gt;

&lt;p&gt;This solution is especially valuable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Development teams&lt;/strong&gt; - workflow unification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New project members&lt;/strong&gt; - quick understanding of available commands&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DevOps practices&lt;/strong&gt; - deployment standardization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rails learning&lt;/strong&gt; - focus on development rather than environment setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;RailsStart&lt;/a&gt; proves that a properly organized &lt;code&gt;Makefile&lt;/code&gt; can transform a complex &lt;strong&gt;Docker&lt;/strong&gt; + &lt;strong&gt;Rails&lt;/strong&gt; environment into a simple and intuitive development tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Glossary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Host machine&lt;/strong&gt; - a physical or virtual computer on which Docker and other software runs. In the context of the article - your working machine (macOS, Linux, Windows).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container&lt;/strong&gt; - an isolated application runtime environment created using containerization technology. Contains the application and all its dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt; - a platform for developing, delivering, and running applications in containers. &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;docker.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Compose&lt;/strong&gt; - a tool for defining and running multi-container Docker applications. &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;docs.docker.com/compose&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make&lt;/strong&gt; - a build automation utility for managing compilation and command execution. &lt;a href="https://www.gnu.org/software/make/" rel="noopener noreferrer"&gt;gnu.org/software/make&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt; - a configuration file for the Make utility, containing rules and commands for task automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rails (Ruby on Rails)&lt;/strong&gt; - a web framework for the Ruby programming language. &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;rubyonrails.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt; - a distributed version control system. &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;git-scm.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WSL (Windows Subsystem for Linux)&lt;/strong&gt; - a Windows subsystem for Linux that allows running a Linux environment on Windows. &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/" rel="noopener noreferrer"&gt;docs.microsoft.com/windows/wsl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Install Ruby on Rails 8 on Windows</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Wed, 01 Oct 2025 07:05:09 +0000</pubDate>
      <link>https://dev.to/the_teacher/how-to-install-ruby-on-rails-8-on-windows-3kgg</link>
      <guid>https://dev.to/the_teacher/how-to-install-ruby-on-rails-8-on-windows-3kgg</guid>
      <description>&lt;h2&gt;
  
  
  Rails Start!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/the-teacher/rails-start" rel="noopener noreferrer"&gt;"Rails Start"&lt;/a&gt; is a starter kit for Ruby on Rails applications, designed to help developers quickly set up a new project with essential features and best practices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This project is a perfect choice for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enterprises&lt;/strong&gt; looking to standardize their Rails application setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freelancers and agencies&lt;/strong&gt; to kickstart client projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Online education platforms&lt;/strong&gt; to start teaching Ruby on Rails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Individual developers&lt;/strong&gt; who want a solid foundation for their Rails applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; and Docker Compose installed on your machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;git&lt;/strong&gt; installed (usually comes pre-installed on MacOS and Linux).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;make&lt;/strong&gt; utility installed (usually comes pre-installed on MacOS and Linux).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WSL2&lt;/strong&gt; (For Windows users) with a Linux distribution (like Ubuntu) is recommended.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Use (MacOS / Linux)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git clone https://github.com/the-teacher/rails-start.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd rails-start&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make rails-start&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it! Very simple!&lt;/p&gt;

&lt;p&gt;Now visit: &lt;code&gt;http://localhost:3000&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9bhh262wji8gghr7q5zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9bhh262wji8gghr7q5zv.png" alt=" " width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use (Windows WSL2)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;cmd&lt;/code&gt; or &lt;code&gt;PowerShell&lt;/code&gt; and run:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install WSL2 and Ubuntu (if not installed yet):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--set-default-version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;WSL&lt;/code&gt; and install &lt;code&gt;make&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apt-get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git clone https://github.com/the-teacher/rails-start.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd rails-start&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make rails-start&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it! Very simple!&lt;/p&gt;

&lt;p&gt;Now visit: &lt;code&gt;http://localhost:3000&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl83o6uro2fq1y1l9a7er.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl83o6uro2fq1y1l9a7er.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>opensource</category>
      <category>docker</category>
    </item>
    <item>
      <title>miniframe-router: Router for Express.JS Applications</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Mon, 30 Dec 2024 12:11:09 +0000</pubDate>
      <link>https://dev.to/the_teacher/miniframe-router-router-for-expressjs-applications-2bk7</link>
      <guid>https://dev.to/the_teacher/miniframe-router-router-for-expressjs-applications-2bk7</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/miniframe-router" rel="noopener noreferrer"&gt;miniframe-router&lt;/a&gt;&lt;/strong&gt; — a minimalist router for Express.JS applications, inspired by Ruby on Rails. Here’s how I made it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5t1zaooq2323t3sxf37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5t1zaooq2323t3sxf37.png" alt="Image description" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Example of how routing might look in a simple application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Root routes&lt;/span&gt;
&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index#home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Basic CRUD routes&lt;/span&gt;
&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#show&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id/destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Posts routes with scope&lt;/span&gt;
&lt;span class="nf"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#show&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts/:id/destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;I hadn’t written NodeJS applications for about 10 years. Curious about Telegram Mini Apps, I decided to build a few simple projects to explore this new field.&lt;/p&gt;

&lt;p&gt;For this, I needed routing for the backend of my applications. Existing solutions didn’t quite impress me, so I decided to create my own router — simple, effective, and inspired by Ruby on Rails. It was also a great opportunity to refresh my knowledge of creating NPM packages, something I hadn’t done in 9 years.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Expectations for the Router:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Routing is defined in a separate file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This simplifies the application structure and avoids cluttering the main application file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;routeScope&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;miniframe-router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Root routes&lt;/span&gt;
&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index#home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Basic CRUD routes&lt;/span&gt;
&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#show&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id/destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users#destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Posts routes with scope&lt;/span&gt;
&lt;span class="nf"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#show&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/posts/:id/destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts#destroy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;getRouter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The router integrates into the main ExpressJS file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A simple and effective entry point for the application: &lt;code&gt;src/index.js&lt;/code&gt; or &lt;code&gt;src/main.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;getRouter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;&amp;lt;&amp;lt; DEFINE ROUTES&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getRouter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;&amp;lt;&amp;lt; APPLY ROUTES&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Demo app is running on http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Following conventions for connecting controllers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Controllers are located in the &lt;code&gt;src/controllers&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;MyApp
└── src
    ├── controllers
    │   ├── blog
    │   │   └── postsController.ts
    │   ├── indexController.ts
    │   └── usersController.ts
    ├── index.ts
    └── routes
        └── index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  File Structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Routes are defined in &lt;code&gt;src/routes/index.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Controllers contain the logic for handling requests:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: &lt;code&gt;src/controllers/usersController.ts&lt;/code&gt; (or &lt;code&gt;.js&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;List of all users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Showing details for user &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Creating new user with data: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Updating user &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with data: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Deleting user &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a development container using &lt;strong&gt;Docker&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set up &lt;strong&gt;ESBuild&lt;/strong&gt; for compiling TypeScript to JavaScript.&lt;/li&gt;
&lt;li&gt;Install &lt;strong&gt;Jest&lt;/strong&gt; for testing.&lt;/li&gt;
&lt;li&gt;Write tests to validate the first version of the router.&lt;/li&gt;
&lt;li&gt;Implement the router until all tests pass.&lt;/li&gt;
&lt;li&gt;Recover my long-unused NPM credentials (after 9 years).&lt;/li&gt;
&lt;li&gt;Publish the NPM package as version &lt;code&gt;1.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fix critical installation bugs and remove versions &lt;code&gt;1.0.0&lt;/code&gt; and &lt;code&gt;1.1.0&lt;/code&gt;. 😄&lt;/li&gt;
&lt;li&gt;Apply the router to a production project with a dozen routes.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Q&amp;amp;A
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why even do this? There are so many existing solutions!
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;It’s &lt;strong&gt;interesting&lt;/strong&gt;, &lt;strong&gt;useful&lt;/strong&gt;, and contributes to diversity in solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Why so simple? Shouldn’t it be more complex?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Following the &lt;strong&gt;KISS&lt;/strong&gt; principle. Complexity can be added later as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Why controllers? Aren’t they unnecessary?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Controllers are convenient for small projects. Higher abstractions like Action/Operation-like solutions are better suited for larger systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Is this solution even functional?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Absolutely! The router was used in a small production app and performed perfectly with dozens of routes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What size projects can it handle?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;miniframe-router&lt;/code&gt;&lt;/strong&gt; is suitable for applications with dozens of routes. There are no strict size limitations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Project code and documentation: &lt;a href="https://github.com/the-teacher" rel="noopener noreferrer"&gt;GitHub - miniframe-router&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NPM package: &lt;a href="https://www.npmjs.com/package/miniframe-router" rel="noopener noreferrer"&gt;miniframe-router&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like, share, and subscribe! Constructive feedback is always welcome.&lt;/p&gt;

&lt;p&gt;Author's page: &lt;a href="https://github.com/the-teacher" rel="noopener noreferrer"&gt;GitHub - the-teacher&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>express</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Vue. Slots. First touch</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Wed, 17 Jan 2024 13:09:34 +0000</pubDate>
      <link>https://dev.to/the_teacher/vue-slots-first-touch-3eee</link>
      <guid>https://dev.to/the_teacher/vue-slots-first-touch-3eee</guid>
      <description>&lt;p&gt;First time I met using slots in Vue.js&lt;/p&gt;

&lt;p&gt;I wanted to figure out how it works, because I could not develop tests without a deep understanding of this concept.&lt;/p&gt;

&lt;p&gt;Let's see how it works&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;components/MyComponent.vue&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greetingMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;someNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greetingMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/slot&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greetingMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/slot&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;footer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greetingMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/slot&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;App.vue&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/MyComponent.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;headerProps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;HEADER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;headerProps&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;defaultProps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;defaultProps&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;footer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ text, count }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;FOOTER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/MyComponent&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Slots inside Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;By default a slot works as a &lt;code&gt;{ children }&lt;/code&gt; parameter in React components. It provides a way to take a content of a Component (&lt;code&gt;&amp;lt;MyComponent&amp;gt;CONTENT HERE&amp;lt;/MyComponent&amp;gt;&lt;/code&gt;) and place it inside internals of the component.&lt;/li&gt;
&lt;li&gt;In a component Slot reserves a place where a content will be placed, if the content comes from the parent level.&lt;/li&gt;
&lt;li&gt;A component may have multiple slots inside&lt;/li&gt;
&lt;li&gt;Slot without a name, by default has name &lt;code&gt;default&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Slots outside Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WOW!&lt;/strong&gt; From the inside of the component slots may pass data on the level of parent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;slot name="header" :text="hello"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;passes the &lt;code&gt;text&lt;/code&gt; variable to &lt;code&gt;template&lt;/code&gt; (to the upper level)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;template #header="headerProps"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;now inside &lt;code&gt;&amp;lt;template #header&amp;gt;&lt;/code&gt; you can use&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{{ headerProps.text }}&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WOW!&lt;/strong&gt; Ordering of slots inside a component defines an order outside, and affects on ordering of templates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if here we have an order: &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;headerProps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;HEADER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;headerProps&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;defaultProps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;defaultProps&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;footer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ text, count }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;FOOTER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/MyComponent&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but if we define the order of slots like that &lt;code&gt;footer&lt;/code&gt;, &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;footer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greetingMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/slot&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greetingMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/slot&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greetingMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/slot&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it will produce the result&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;FOOTER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;

&lt;span class="nx"&gt;HEADER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nl"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was pretty unexpected to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackblitz.com/edit/vitejs-vite-nccrbc?file=src%2FApp.vue" rel="noopener noreferrer"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>slot</category>
      <category>slots</category>
    </item>
    <item>
      <title>Rails 7. Start Kit Loves Nginx</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Mon, 18 Sep 2023 08:14:51 +0000</pubDate>
      <link>https://dev.to/the_teacher/rails-7-start-kit-loves-nginx-oic</link>
      <guid>https://dev.to/the_teacher/rails-7-start-kit-loves-nginx-oic</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/the-teacher/rails7-startkit" rel="noopener noreferrer"&gt;Rails 7. Start Kit&lt;/a&gt; is a great choice for any kind of startups and developers who wants to save time in launching a new Rails application on any platform.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/f6aAwAMH4Q8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;At this weekend I've added NGINX to my start kit setup.&lt;/p&gt;

&lt;p&gt;Time to time it is important to debug and check an application in mode that is close to the real production environment. Using NGINX helps to do it. I have added certificates to provide access via &lt;code&gt;https&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this &lt;a href="https://github.com/the-teacher/rails7-startkit/pull/41" rel="noopener noreferrer"&gt;PULL REQUEST&lt;/a&gt; You can check changes related to the enhancement.&lt;/p&gt;

&lt;h2&gt;
  
  
  /etc/hosts
&lt;/h2&gt;

&lt;p&gt;To have an access to the project on local machine do not forget config your &lt;code&gt;/etc/hosts&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2F9f740e81-db95-4b7b-976a-55b42394dc42" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-09-18 at 10 12 29" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2F9f740e81-db95-4b7b-976a-55b42394dc42" width="800" height="49"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2Ffab9a943-0891-41b5-adfa-0959a2793c1e" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-09-18 at 10 12 04" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2Ffab9a943-0891-41b5-adfa-0959a2793c1e" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How it looks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;http&lt;/th&gt;
&lt;th&gt;https&lt;/th&gt;
&lt;th&gt;certificate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img alt="Screenshot 2023-09-17 at 14 36 32" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2Fa075267d-5f64-4c20-9d80-e45370a551c5" width="800" height="655"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img alt="Screenshot 2023-09-17 at 15 35 27" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2F047a4c76-4866-44af-b5ce-11daf66c9b18" width="800" height="637"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img alt="Screenshot 2023-09-17 at 15 39 00" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2F6db1e6b9-67e5-4b03-9e67-3b46c84ccf5a" width="800" height="974"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Naming and Conventions note
&lt;/h2&gt;

&lt;p&gt;Time to time people ask me, - "Why do you name configuration files so?". They mean that I &lt;strong&gt;underscore and uppercase&lt;/strong&gt; some configuration files and folders like you can see it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2Ffaf5e265-39e4-48e6-a48d-494863b07726" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-09-18 at 10 02 18" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fthe-teacher%2Frails7-startkit%2Fassets%2F496713%2Ffaf5e265-39e4-48e6-a48d-494863b07726" width="800" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do it to highlight some important configuration files, folders and other stuff for demonstration and education purposes.&lt;/p&gt;

&lt;p&gt;If you do not like naming like that or my way to place configuration files - you always can change it following your personal preferences. &lt;/p&gt;
&lt;h3&gt;
  
  
  One-liner for launching &lt;code&gt;Ruby on Rails&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;❤️ &lt;strong&gt;Linux / MacOS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/the-teacher/rails7-startkit.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;cd &lt;/span&gt;rails7-startkit &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ruby bin/setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💙 &lt;strong&gt;Windows&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/the-teacher/rails7-startkit.git &amp;amp; &lt;span class="nb"&gt;cd &lt;/span&gt;rails7-startkit &amp;amp; ruby bin/setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;On your host you have to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Any version&lt;/strong&gt; of Ruby&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any version&lt;/strong&gt; of Git&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any version&lt;/strong&gt; of Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Like, Share, Tell to your Colleagues
&lt;/h3&gt;

&lt;p&gt;👉 The project needs for your help to make it helpful for as much people is it possible.&lt;/p&gt;

&lt;p&gt;Please Like 👍 , Share 💁   and Tell 📣 to your Colleagues! &lt;/p&gt;

&lt;p&gt;❤️ Happy coding with &lt;a href="https://github.com/the-teacher/rails7-startkit" rel="noopener noreferrer"&gt;Rails 7. Start Kit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>development</category>
      <category>docker</category>
      <category>startup</category>
    </item>
    <item>
      <title>RubyMine. How to remove trailing whitespaces</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Mon, 22 May 2023 08:29:51 +0000</pubDate>
      <link>https://dev.to/the_teacher/rubymine-trailing-whitespaces-chi</link>
      <guid>https://dev.to/the_teacher/rubymine-trailing-whitespaces-chi</guid>
      <description>&lt;p&gt;I noticed that by default my new code editor does not remove trailing whitespaces. There is the setting is placed!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9kgi6y9uvq681iya970.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9kgi6y9uvq681iya970.png" alt="How to setup removing of trailing whitespaces" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rubymine</category>
      <category>settings</category>
    </item>
    <item>
      <title>RubyMine. How to Increase/Decrease font size</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Mon, 15 May 2023 07:41:49 +0000</pubDate>
      <link>https://dev.to/the_teacher/rubymine-increasedecrease-font-size-51d</link>
      <guid>https://dev.to/the_teacher/rubymine-increasedecrease-font-size-51d</guid>
      <description>&lt;p&gt;To change the font size in the editor you need to press &lt;strong&gt;SHIFT + CONTROL&lt;/strong&gt; and &lt;strong&gt;point or comma&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bslf6hxjge9o6ayngb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bslf6hxjge9o6ayngb3.png" alt="Keyboard" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding&lt;/p&gt;

</description>
      <category>rubymine</category>
      <category>ruby</category>
      <category>editor</category>
    </item>
    <item>
      <title>RubyMine. How to Show/Hide terminal panel</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Sun, 14 May 2023 13:16:10 +0000</pubDate>
      <link>https://dev.to/the_teacher/rubymine-showhide-terminal-panel-4be8</link>
      <guid>https://dev.to/the_teacher/rubymine-showhide-terminal-panel-4be8</guid>
      <description>&lt;p&gt;This nice Terminal panel does not show/hide when you just press &lt;strong&gt;OPTION key + F12&lt;/strong&gt; as it is described in a tooltip&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyic98j2koqmkywuyjpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyic98j2koqmkywuyjpn.png" alt="Trminal" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is because on MacOS functional keys are being used by operation system. For example to control sound.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5z6dgdrdc082m0j4cs3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5z6dgdrdc082m0j4cs3k.png" alt="MacOS keyboard shortcuts" width="800" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can just turn this behaviour off. I do not like the idea because I like it.&lt;/p&gt;

&lt;p&gt;To use &lt;strong&gt;OPTION key + F12&lt;/strong&gt; you just need to use &lt;strong&gt;FN&lt;/strong&gt; key as well.&lt;/p&gt;

&lt;p&gt;The final combo is &lt;strong&gt;FN key + OPTION key + F12&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>RubyMine. How to Open a Folder with a Single Click</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Sun, 14 May 2023 06:52:32 +0000</pubDate>
      <link>https://dev.to/the_teacher/rubymine-open-a-folder-with-a-single-click-2ijl</link>
      <guid>https://dev.to/the_teacher/rubymine-open-a-folder-with-a-single-click-2ijl</guid>
      <description>&lt;p&gt;Jetbrains gave me a license for developing my OpenSource project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn8qf1c3c1roq3m09tu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn8qf1c3c1roq3m09tu6.png" alt="License" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make my development experience better I set up the option - &lt;strong&gt;Open files with Single Click&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqp199knsts3zmxyupm91.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqp199knsts3zmxyupm91.png" alt="Settings" width="800" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Surprisingly there is no an option to do the same with Folders&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtrack.jetbrains.com/issue/IDEA-142105" rel="noopener noreferrer"&gt;https://youtrack.jetbrains.com/issue/IDEA-142105&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0xp858ap007fqq2n91d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0xp858ap007fqq2n91d.png" alt="Tracker" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately there is an old but old plugin to manage it&lt;/p&gt;

&lt;p&gt;&lt;a href="https://plugins.jetbrains.com/plugin/12778-quick-file-preview" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/12778-quick-file-preview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsif453mam5bczsb1nr86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsif453mam5bczsb1nr86.png" alt="Image description" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now everything works like I want.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>jetbrains</category>
      <category>opensource</category>
    </item>
    <item>
      <title>RSpec. let and let!</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Mon, 24 Apr 2023 18:31:20 +0000</pubDate>
      <link>https://dev.to/the_teacher/rspec-let-and-let-1go4</link>
      <guid>https://dev.to/the_teacher/rspec-let-and-let-1go4</guid>
      <description>&lt;p&gt;After years being out of the Rails ecosystem I was curious what is the difference between &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;let!&lt;/code&gt; in rspec tests. I just forgot.&lt;/p&gt;

&lt;p&gt;There is a simple case to demonstrate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'Creating.'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'Exists'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  1&lt;span class="o"&gt;)&lt;/span&gt; User Creating. Exists
     Failure/Error: expect&lt;span class="o"&gt;(&lt;/span&gt;User.count&lt;span class="o"&gt;)&lt;/span&gt;.to eq 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with &lt;code&gt;let!&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'Creating.'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'Exists'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It gives: &lt;code&gt;User Creating. Exists&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;let&lt;/code&gt; we create an object when we first time to use it.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;let!&lt;/code&gt; we create an object when we declare it.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>rspec</category>
      <category>testing</category>
    </item>
    <item>
      <title>How to write a View test in Rails with RSpec</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Fri, 21 Apr 2023 16:49:28 +0000</pubDate>
      <link>https://dev.to/the_teacher/how-to-write-a-view-test-in-rails-with-rspec-1kci</link>
      <guid>https://dev.to/the_teacher/how-to-write-a-view-test-in-rails-with-rspec-1kci</guid>
      <description>&lt;p&gt;I want to write a &lt;code&gt;View&lt;/code&gt; test. What should I do?&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1. Learn the view template
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="n"&gt;content_for&lt;/span&gt; &lt;span class="ss"&gt;:head&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Project Name&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
    &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt;
    &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;vite_asset_url&lt;/span&gt; &lt;span class="s1"&gt;'images/logo.jpg'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="vi"&gt;@blogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I see&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;View variable &lt;code&gt;@blogs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Rails helper &lt;code&gt;vite_asset_url&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2. How to &lt;code&gt;stub&lt;/code&gt; a rails helper?
&lt;/h3&gt;

&lt;p&gt;To do that I'm going to use the following way. Here in &lt;code&gt;view&lt;/code&gt; I stub &lt;code&gt;vite_asset_url&lt;/code&gt; and it will return a string "vite_asset_url".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;
  &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:vite_asset_url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"vite_asset_url"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3. How to &lt;code&gt;stub&lt;/code&gt; a view variable?
&lt;/h3&gt;

&lt;p&gt;To do that I use &lt;code&gt;assign&lt;/code&gt; test helper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:blogs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;blog1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blog2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blog2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4. How a test should look?
&lt;/h3&gt;

&lt;p&gt;It looks like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"site/landing/index"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :view&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:published_blogs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;create_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:blog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:for_blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="s2"&gt;"Blog Title &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save!&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;
      &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:vite_asset_url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"vite_asset_url"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"renders attributes in show page"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:blogs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;published_blogs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;render&lt;/span&gt;

    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Blog Title 1/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Blog Title 2/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Blog Title 3/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it!&lt;br&gt;
Happy Coding!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>testing</category>
      <category>rspec</category>
    </item>
    <item>
      <title>Testing Rails root route</title>
      <dc:creator>Ilya N. Zykin</dc:creator>
      <pubDate>Fri, 21 Apr 2023 11:29:44 +0000</pubDate>
      <link>https://dev.to/the_teacher/testing-rails-root-route-58dc</link>
      <guid>https://dev.to/the_teacher/testing-rails-root-route-58dc</guid>
      <description>&lt;p&gt;Now I need to test a root route in a Rails App&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1. Learning the routing file
&lt;/h3&gt;

&lt;p&gt;File: &lt;code&gt;config/routes.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'root#index'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2. Adding a test
&lt;/h3&gt;

&lt;p&gt;File: &lt;code&gt;spec/routing/root_spec.rb&lt;/code&gt;. This time I didn't use &lt;code&gt;describe&lt;/code&gt;, only &lt;code&gt;it&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;root_path&lt;/code&gt; is a Rails routing helper that is equal to &lt;code&gt;/&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'Root Route'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :routing&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'leads to a correct controller and action'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt; &lt;span class="n"&gt;route_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"root#index"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'does not exist'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;post: &lt;/span&gt;&lt;span class="n"&gt;root_path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;not_to&lt;/span&gt; &lt;span class="n"&gt;be_routable&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3. Running the spec
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rspec spec/routing/root_spec.rb &lt;span class="nt"&gt;--format&lt;/span&gt; documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it!&lt;br&gt;
Happy coding!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>testing</category>
      <category>rspec</category>
      <category>routing</category>
    </item>
  </channel>
</rss>
