Where Ruby ends and Rails begins
That might sound like an odd title for experienced Ruby on Rails Developers. But If you’re new to Ruby on Rails you may relate to it and find the differentiation helpful.
Last night I received a question from a reader:
“I just started a new job and they’re all RoR and I have zero Ruby experience (long time Perl, JS….some Python and Java). I can’t figure out where Ruby ends and Rails begins.” — Steven
When I received this question from Steven, my first intuition was to tell him my usual answer “Rails is written in Ruby, and Ruby is a coding language” (And I did ). But then I realized that I wasn’t actually answering his question. You see, for Rubyist, this question is a no brainer. But when you think of it from the perspective of someone that was just introduced to ruby, I can see how that can be confusing. Imagine being thrown on a Ruby on Rails project for the first time and you get used to seeing methods such as titleize or constantize. Then, you go on IRB (Ruby interactive shell ) and try to write a program by using these methods and you have absolutely no idea why you’re consistently getting NoMethodErrors.
In this article, I’m going to try to answer Steven’s question. To do so I’ll need to start with Rack. You might think “Why do I need to know about rack?” at this very moment. Well bear with me, it will all make sense in the end.
What is Rack? ( Not Rake )
Rack != Rake
Maybe you didn’t know this, but Rails is a Rack app written in Ruby. But what is Rack? Rack provides a simple interface between a web server and a web framework. You can actually write a simple web application by just using rack.
It’s so barebone that we can write a web app in a 15 seconds. Ready? 1…2…
$ gem install rack
$ gem install thin
$ echo "run ->(env) { [200, {'Content-Type' => 'text/html'}, ['Hello World!']] }" > simple_app.ru
$ rackup simple_app.ru
That’s it. We have a web app.
Rack essentially allows you to create a very barebone server application.
What is Sinatra?
Sinatra is a rack app as well. I wouldn’t go as far as calling Sinatra a framework’; it’s just a DSL on top of Rack that makes it easy to create web applications.
Now you might wonder, why do I need Sinatra when I can easily create an app in 10 seconds with Rack. Well creating a simple “Hello World” application is easy with Rack, but creating a much more complicated web application would be a lot of work with it. You would essentially have to write much more custom code that you wouldn’t have to with Sinatra or Rails. Rack is so barebone that Sinatra is like adding milk in your coffee.
What is Rails?
If you liked my analogy above, Rails is the Sugar, and the Cinamon, … and the bread with butter in your coffee. Yes, in short, It’s like Sinatra on steroids (Or with sugar 😂).
Just like Sinatra, it makes it easier to create web applications. It also comes with a bunch of features that help you with tons of other stuff.
Why do you need to know about Rack and Sinatra?
You don’t need to know about either, but it will certainly help you better understand what Rails is doing as a framework. Understanding how Sinatra works will clarify everything about Rails in your head (including the model, view, controller logic).
To be fair, you actually do need to know about Rack.
I recommend that you get familiar with rack and Sinatra because If you try to build a site using Rack, and then Sinatra you’ll understand what value Sinatra is adding to Rack and then what value Rails is adding to rack in comparison to Sinatra.
So…. Where Ruby ends?
Since rails is a framework, it comes with a lot of methods that weren’t in the original programming of Ruby. To illustrate this I’m going to show you a few code examples in IRB (Ruby interactive shell — without loading Rails) and in the Rails Console ( where rails is loaded). The only difference is that the rails console is an interactive shell that loads all the config of my Rails application so we get all the Rails method with it.
You can access IRB by typing:
$ irbIf you already have a rails application you can access the console by typing the following line in the root of your Rails application:
$ rails consoleFeel free to type the codes that follow. That will allow you to learn by doing and follow along the way.
Alright, Let’s take the rails method humanize which turns a string into a title by changing the first letter of the first word to uppercase.
(RAILS CONSOLE)
> 2.7.0 :002 > a = "rails example"
> 2.7.0 :011 > a.humanize
=> "Rails example"As you can see this is a very useful method, but this method doesn’t exist in Ruby. It’s a Rails method.
Let’s try to call this method when Rails is not loaded in our IRB console:
(IRB)
2.7.0 :001 > a = "ruby example"
2.7.0 :002 > a.humanize
Traceback (most recent call last):
4: from /Users/richardson/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `<main>'
3: from /Users/richardson/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `load'
2: from /Users/richardson/.rvm/rubies/ruby-2.7.0/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in `<top (required)>'
1: from (irb):2
NoMethodError (undefined method `humanize' for "ruby example":String)Notice that we’re now getting an error?
NoMethodError (undefined method `humanize' for "rails method":String)So what happened? I’m glad you asked! 👏 It’s quite straightforward actually .humanize wasn’t defined in Ruby! But if you load Rails, with all its classes then you’ll have that method.
How you can investigate methods
I want to give you the tool to do this type of investigation on your own in the future. So let do some additional investigation so that you can better understand what’s happening here:
2.7.0 :014 > a.methods.grep(/humanize/)
=> [:humanize]
> 2.7.0 :011 > a.class
=> StringIn the code above: .methods returns an array of all the methods for an object. and .grep allows us to pass a keyword to return only what we want
By the way /humanize/ is actually called a REGEX, but no need to complicate things right now...
Since a is an instance of String, when we call .humanize, we’re calling an instance method. With the code above I’m checking that an instance method .humanize exist on our instance a. And it does!
If I wanted to check that a method exists on the class itself I would have done.
> 2.7.0 :011 > a.class
=> String
2.7.0 :049 > a.class.methods.grep(/humanize/)
=> []Here I’m checking if a method .humanize exists in the String class. It’s important to separate instance methods and class methods here. Te method .humanize is an instance method so it can only be called on the instance of a class. The .humanize method in Rails was written to be called on instances of the class String. ( We will see where it is defined in the rails code shortly )
So how come we’re able to call this method in the Rails Console and not in IRB? That’s because Ruby doesn’t define .humanize, Rails does. So to get it in IRB we would need to load the Rails environment.
humanize is not the only method that is defined in Rails and not Ruby. Rails is an incredible framework that comes with many handy methods such as:
pluralize titleize underscore lowercase uppercase 2.days.from_now ( Yes seriously! )
and so on… Rails defines these instance methods in classes such as String, Integer and Float by overwriting the definition of these objects.
Everything in Ruby is an Object.
Let’s write a custom “Rails” Method
Want to try it? We’re going to overwrite the String class so we can create our own custom methods — the same way Rails does it. Let’s go back to our rails console so we can do it in the context of Rails first.
( Rails Console )
2.7.0 :022 > class String
2.7.0 :023 > def custom_method?
2.7.0 :024 > puts "I'm a custom method"
2.7.0 :025 > end
2.7.0 :026 > end
=> :custom_method?
2.7.0 :028 > a = "Taekwendo"
2.7.0 :028 > a.custom_method?
I'm a custom method
=> nilNow that we’ve taught the class String some taekwondo, Let’s try to run our new method in the IRB console… Spoiler alert: It won’t work.
( IRB )
2.7.0 :028 > a = "Taekwendo"
2.7.0 :028 > a.custom_method?
Traceback (most recent call last):
4: from /Users/richardson/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `<main>'
3: from /Users/richardson/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `load'
2: from /Users/richardson/.rvm/rubies/ruby-2.7.0/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in `<top (required)>'
1: from (irb):4
NoMethodError (undefined method `custom_method?' for "":String)Yes, the String class in ruby has absolutely no idea what custom_method is because we never defined it. We never overwrote the String class to teach it that method.
Rails under the microscope
You now understand why Ruby doesn’t necessarily have the methods defined in Rails. Or as you call it “Where Ruby ends” . I think that it will be a lot easier to understand the separation between ruby and rails method now.
Remember how I mentioned that Rails was written in Ruby? We can actually go to the Rails Github Repository and see where the .humanized method was defined in Rails.

mmh… Where is this bad boy? Oh! Here it is…😆




