Where Ruby ends and Rails begins

Richardson Dackam
Ruby or Rails
Published in
9 min readMar 18, 2020

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:

$ irb

If you already have a rails application you can access the console by typing the following line in the root of your Rails application:

$ rails console

Feel 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
=> String

In 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
=> nil

Now 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.

https://github.com/rails/rails

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

in rails/activesupport/lib/active_support/core_ext/string/inflections.rb

We are in the inflections.rb file. As expected Rails defines the instance method humanize by overwriting the String class. Bam! This is usually where I would say Mic drop but we’re not done yet.

Conclusion

If you’re still wondering how you can tell if one method is defined in Rails and Ruby. You can sometimes deduct it based on your environment. For example, if you’re just writing an application with Ruby, and you’re not loading the rails gem, then you’re definitely not going to have Rails methods in that environment. Now, if you’re within a rails application, that’s different. You will probably have the rails methods of your rails version.

You might run into scenarios where Rails is not installed but those methods are somehow defined. That could happen if someone decided to overwrite these classes within the Ruby code. At least now you’ll know what to look for.

Ruby Documentation
https://www.ruby-lang.org/en/documentation/

Rails API Documentation
https://api.rubyonrails.org/

If you were hoping for a shortcut — I’m sorry to say this but — the best way to check is by looking at the documentation. Check your current rails version and check the documentation for that rails version and check what methods are defined there. This is still the best way to investigat “Where Ruby ends and Rails begins”. And Steven, I hope this article answered your question.

👏 Please don’t forget to clap If you enjoyed this article and found it helpful.

Stuff I also wrote

I try to write often. I usually get inspired by questions from readers so don’t hesitate to reach out here or on my youtube.

  1. How to land your first Ruby on Rails job. 👨‍💻
  2. Why Googling is the most important skill a developer *must* have. 🕵️‍♂️
  3. How I Trained to Learn Rails 🥋
  4. Everything you should know about the obscure world of JRUBY — JRuby with Rails under a Microscope 🙀
  5. How to get robbed by insecure practices


Richardson Dackam is a Freelance
Senior Ruby on Rails Developer and Youtuber located in Toronto, Ontario, Canada. | https://github.com/richardsondx

I don’t like to put helpful resources behind a paywall… If you want to see more articles like this one without a paywall and would like to support my work, you can do so by becoming a Patreon: Click here to support my work.

If you’d like to get more advice on how you can learn to code, become a software engineer and become a successful independent freelancer, Subscribe to my Youtube channel [ Click Here To Subscribe ] and don’t forget to click on the bell to get notified whenever I post new videos.

--

--

Richardson Dackam
Ruby or Rails

Building and maintaining apps while teaching the process with systems you can steal. | Learn to build apps @ richdackam.com | Build one @ Richdx.com |