00:00:10.120
My name is Nate Berkopec. Welcome to the month of May! I'm also known by the name of 'Grand Maester Nate.' I'm an expert in Rails magic. I've forged my links at the Oldtown Great Citadel. Just kidding—Rails is not actually magic. David Heinemeier Hansson (DHH) does not actually sacrifice chickens in his backyard to make all the components work. Today, we're going to talk a little bit about some of that 'magic' and explore the different parts of the Rails framework. We'll examine how they fit together when you type 'rails new' and receive a vast array of folders and files. What are they all actually doing for you? Can we get rid of all of them? Ultimately, we aim to create a Rails application in a tweet!
00:01:38.880
When I mention 'Rails,' what comes to mind? Do you think of it as bloated or lightweight? When you have a Rails application and it spans 50,000 lines, does it feel a bit overwhelming? Do you associate Rails with well-architected code or do you picture spaghetti code? I've heard action controllers described as a 'crack den of inheritance.' When you think of Rails, do you consider it modular or monolithic? Many users on Stack Overflow complain about CSRF protection not working, with common advice being to simply turn off CSRF protection. This observation suggests that people take a rather cavalier approach to security, akin to saying, 'If it breaks things, let's ignore it.' When you think of Rails, do you think of its speed, or do you associate it with slowness? Does your Rails application sometimes feel like it's moving at a leisurely pace?
00:03:39.720
Despite the negative mental associations many people have with Rails, I believe it's a lightweight, well-architected, and modular framework for creating speedy web applications. Unfortunately, it often fails to advertise itself this way. Part of the blame lies with how DHH describes Rails. In his keynote last year at RailsConf 2015, he depicted Rails as a 'prepper backpack' for doomsday, implying that he wanted to be able to rebuild base camp with just Rails, should the internet collapse. This expansive vision contrasts sharply with the simplicity advertised by other frameworks. However, it does not imply that Rails cannot be simple or lightweight.
00:05:01.600
In this talk, we will start with the file structure and boilerplate generated by the 'rails new' command. We will systematically remove the components until we reach a concise application of just 140 characters. The first step after typing 'rails new' is to add a controller. Our app needs to do something, so I will add a 'Hello World' controller that renders 'Hello, World!' in plain text. I also need to add a route for this in the config/routes.rb file.
00:07:02.199
At this point, we have 433 lines of code generated by 'rails new,' spread across 61 unique files. That’s quite a lot, including configuration files and Ruby files. Therefore, our initial step should be to remove all the empty folders and files. Many folders generated by 'rails new' are empty, often included just to force Git to track them. However, Rails doesn't require these empty folders to function. For instance, we can safely delete the entire 'lib' folder, 'log,' and 'temp' directories since these will be recreated when needed. Also, we can delete the 'vendor' folder for our 'Hello World' application since we don't need any assets.
00:08:10.960
Next, we should eliminate all the boilerplate empty files that serve no purpose. Many of the files in the 'config/initializers' directory are just blank with comments that provide no real functionality. They're simply signposts suggesting where to put code without being useful in and of themselves. We can delete the entire 'public' directory, as files like 500.html and 404.html are designed to display error messages but are not necessary for our simple application.
00:09:13.640
My main point is that empty does not equal worthless. One of the most important things that 'rails new' does is create these empty, comment-filled files because they establish a common vocabulary. When starting a new Rails application, you know where to find the domain model business logic, typically in app/models. You can expect the HTTP-related code to be in app/controllers and the jQuery plugins likely found in vendor/assets/javascripts. This structure eases navigation for developers when shifting from one Rails application to another.
00:10:38.680
Moving on to step two, we will delete the entire 'app' folder. Some deletions, like the removal of assets, are straightforward, while components we won't use include 'application.js' and 'CSS.' The actual controller logic will be moved to 'config/application.rb,' and we’ll drop all views and models. Essentially, only the controller remains in a 'Hello World' application. I will eliminate the application controller as well because we don't need a common controller pattern for a single controller application. Therefore, we can place it directly at the end of 'config/application.rb.' If you’re confused about why this is being done, I recommend watching Xavier and Oraz's talk that precedes mine.
00:12:22.600
The next step is to delete the entire 'bin' folder, which contains files aimed at improving development convenience, like 'bin/update' and 'bin/setup.' These files serve as best practice examples for setting up a development environment but can be removed. The other four files—'bin/spring,' 'bin/rake,' 'bin/rails,' and 'bin/bundle'—are simply bin stubs, designed to wrap a gem executable in a bit of environment setup.
00:13:14.680
For our 'Hello World' application, we don't require these bin stubs. Instead, we'll utilize 'config.ru' directly and employ the 'rackup' command. 'Rackup' looks for a 'config.ru' file in the current directory and treats its contents as the body of a block within the code.
00:15:12.680
The 'config.ru' file in a generated Rails application looks quite simple, with a few key actions defined. Essentially, we call the 'Rack' method using our 'config.ru' file, rather than launching 'rails server.' This will execute 'config.ru' directly, achieving the same result without unnecessary overhead.
00:16:21.720
Next, we will only use the components we need from Rails. At the start of 'config/application.rb,' the directive 'require rails/all' loads all the different frameworks in Rails. However, many applications don't actually employ all components, particularly API-only applications. For our Hello World app, we will only utilize the Action Controller framework. The process of modularizing is important to understand, stemming from the merging of a web framework called 'Merb' into Rails to enhance modularity.
00:20:01.559
The Gemfile only needs the 'gem rails' entry. To minimize our application further, we can eventually remove 'bundler,' which, while annoying, technically works. It's crucial to understand that Rails is cautious about what gets included in the Gemfile and the framework itself. Everything in the Gemfile serves as a suggestion and is not mandatory for creating a Rails server.
00:21:36.560
As we strip down the application further, we can discard several configuration files, as they become obsolete when certain components are no longer loaded. By eliminating all the unnecessary files, we can condense our application down into five essential files. Our goal now is to inline these files into one, where we will merge 'boot.rb,' 'environment.rb,' 'application.rb,' and 'production.rb' into 'config.ru.'
00:24:20.360
By performing this consolidation, we'll establish what I consider to be the smallest functional Rails application. Although it may seem contradictory, we accomplish a complete Rails application using only a minimal number of lines. Every 'rackup' file ends with a command to run some rack-compatible application, allowing us to define our application's routes and controllers succinctly.
00:26:18.600
Moreover, all controllers in Rails are essentially just rack applications. This means if you'd like to run the controller as a complete application, you'll organize it within your 'rackup' file. The action method leverages symbols corresponding to respective actions, allowing us to execute the call method on the returned object.
00:29:04.799
To summarize, Rails is a modular framework built upon layers, each component addressing specific functionalities in a Rails application. For instance, ActionController is a direct descendant of ActionController::Metal, which enables you to craft a thin controller. Our final objective is to understand how these pieces all fit together and function as a streamlined web framework.
00:30:05.840
As we bring this all together, remember that not all models need to depend on ActiveRecord. It's perfectly acceptable for objects in the models folder to exist independently, offering a flexible way to utilize ActiveModel for presenting plain Ruby objects that mimic an ActiveRecord-like interaction, without necessitating database persistence.
00:32:00.720
The takeaway here is that this modularity championed in Rails isn't solely for the purpose of performance; understanding how to utilize Rails more effectively can save resources and improve the organization of your code. Try approaching your Rails applications anew, focusing on utilizing only what you need from the framework.
00:39:32.760
Thank you very much for your attention! The full presentation and GitHub repository related to this talk can be found at Nate Berkopec's GitHub, while I also recommend you visit 'railpspeed.com' to explore my course on improving Rails performance.