Learn Ruby and Rails by building your own very simplistic Rails-like Framework.
By Steve Carey - 2/20/2018
Rails is a framework for building web applications using the Model-View-Controller architecture. It uses the Ruby programming language, but is heavily specialized for web applications so it is considered a domain specific language (DSL). In this tutorial we will build a simplistic Rails-like framework with Ruby for the purpose of learning how a web framework like Rails works. Rails is very complicated so we'll only superficially try to mimick Rails. We'll call our framework Jails, because all the good names that rhyme with Rails are already taken.
Why bother? I can answer that for myself and you may find it applies to you as well. Rails is a DSL that abstracts away from the Ruby programming language. You can learn to use out-of-the-box Rails without really understanding Ruby. But you'll never feel like you really get it. So you get a Ruby book and read it. It will tell you all about classes and strings and operators, etc. and will give you small programs to make that you would never use for anything in the real world. But, if you build a web MVC framework from scratch with it, you just might find that you finally get it. And by it I mean Ruby, Rails, HTTP, and programming in general. That was the case for me.
We'll start with an overview of the Rack gem and build a basic Rack application. Then we'll add routes, controllers, views and models with a database until we have a working Rack-based web application. In this case we'll build a blog app. Finally we'll separate out the framework code into a gem so it can be used to build other kinds of applications.
This is the type of tutorial that you'll want to do at least twice. After doing it the first time you'll get the whole picture. Then if you do it again you'll have a better idea of how each step fits into the final picture.Prequisites:
It helps if you are familiar with both Ruby and Rails but if you are a Ruby on Rails newbie you can struggle through it as long as you've done some kind of basic Ruby tutorial. Indeed, my motivation for making this tutorial is that I wish I had done something like this when I was first learning Rails and Ruby. It does assume that you have your Ruby environment set up on your computer meaning you have Ruby and a Ruby Version management tool like Rbenv or RVM; you have a text editor such as SublimeText to write your code; you can find the command-line interface (Terminal on Macs, Bash on PCs - but you'll have to install it); and you are at least somewhat familiar with HTML and CSS.
The official Rails website has an introductory tutorial where you build a simple blog application: guides.rubyonrails.org/getting_started. At a minimum you should be familiar with the concepts covered in that tutorial. In that tutorial you create an article resource for posting and viewing articles. We will follow that lead by building a similar blog application, but will code it from scratch with only the minimally required help from gems.
There are seven parts to this tutorial:
That's a little daunting but well worth it.
The finished version of the app and gem are available at: github.com/steve981cr/jailsfolder
If you find your code doesn't seem to be working at some point, refer to: Error Handling and Debugging Ruby Code
I make some deliberate style choices with the code with the sole purpose of making it as clear as possible what the code is doing.
Rails look and feel: Part of the goal here is to help you understand what Rails is doing. So I'll try to use the same Rails file, class, and method names and functionality as much as possible, but at a very simplistic level. Rails is famous for it's convention over configuration ethos, so we'll follow that lead. Naming conventions is an example. If we have an Article resource, our controller class will be ArticlesController, our model class will be Article, and our database table name will be articles.
Parentheses around arguments: In Ruby, putting parentheses around arguments for a method is optional. That may save a few keystrokes, but it makes it less obvious what is an argument. So I will use parentheses around all arguments.
Long methods: It is common to break methods up into several helper methods. Sometimes this is for DRY (Don't Repeat Yourself) purposes to let parts of the code be used by multiple methods. Other times programmers feel that breaking the different steps of a method out into smaller chunks in their own methods makes it easier to follow. Personally, I find it confusing to jump from method to method before returning your result so many methods will hold as many of the steps as possible to return the requested result.
Return Statements: Every Ruby method returns something. Specifically it returns a single object. That object can be nil, which is the Ruby object representing nothing. It can be an array with multiple elements. But that array is still a single object. If you insert a return statement in your method, then once the line containing the return statement is evaluated it will return the result and exit the method. Ruby methods have an implicit return on the last statement evaluated. So including a return statement at the end of a method is not required and thus not commonly done. However, I will be making extensive use of return statements to make it clear what each method is returning.
Logging: It's quite useful to log what's happening at various steps in your code. It's useful in debugging, but also useful to follow the flow of a client request through various steps in your code all the way to the response. Rails logs messages simultaneously to the terminal and to a file in a log directory. We will log what's going on just in the terminal using puts methods. Puts stands for put string, and will print the argument you provide it to the terminal window that's running your web server. We'll mimick the logging messages that Rails uses for the most part.
Comments: The standard way to document Ruby code is to add comments above methods and classes describing what they do. Ruby's standard library includes the Rdoc module which will document your code based on this principle. We will add short, to-the-point comments above each method. Controller actions will just include the route and HTTP method in the comment.
UNIX/Linux: Most web servers will use a UNIX or Linux operating system. You can think of UNIX and Linux as basically the same thing. UNIX is official, Linux is an open source variant. Since the web server will be using UNIX/Linux, it's easier if you are also using it in your development environment. Mac operating systems use a version of UNIX which is a big reason why they are so popular with web developers. On Windows you can install and use Bash which is a Linux shell. We'll be making extensive use of the UNIX/Linux shell and commands.
KISS: That stands for keep it simple stupid. Rails can get very complex dealing with multiple corner cases. That's great for a robust framework, but good luck reading the source code and trying to figure out what it's doing. Our framework is not robust. It is not meant to be used in production as it is. This is for learning, so we'll err on the side of ignoring the corner cases and giving it only the most basic functionality.
Okay, let's get started.