Rails 3 Baby Steps – Part 1

As you may have seen from many of my past blog posts, I’m a big fan of Ruby. I’ve been a web developer for a long time now, but for the most part I’ve been working solely within the Microsoft .NET world. Over the past few years I’ve been working with ASP.NET MVC heavily for my day to day work, and I love ASP.NET MVC. It is a great framework. However I’ve had my eye on Rails for a long long time, and I even spent a solid chunk of time a few years ago going through “Agile Web Development with Rails” (that is an updated Rails 3 version), but never got into the world of Rails development since my day to day job was on the .NET stack.

Ever since then I’ve been itching to wade back into those waters. Over the past few months I’ve been doing just that, trying to spend some of my free time delving deeper into Rails 3 than I have with any other version. I didn’t want to just slap together a Rails app and say “Done!”, I really wanted to understand the ecosystem and the day-to-day tools that a “real” Rails developer would be using.

Coming into an already mature ecosystem can be a daunting task. Usually the hardest part of it all is trying to filter out the chaff so that you can get to the wheat. If you aren’t familiar with a development ecosystem, you don’t have a good sense for what is needed and what isn’t. You can quickly become overloaded with the minutiae and fail to learn anything. It requires someone with knowledge and time to wade through it and provide you with some guidance.

The problem is, most of the experienced people aren’t interested in blogging about the beginner stuff anymore, they’ve been doing all of this for years, they want to get to the new features and the more advanced stuff that is useful and interesting to them. I hope to help remedy that a little bit with this series.

Over the last few weeks I’ve been digging into Rails 3 in the hopes of getting a grasp on the tools and environment. I’ve avoided blogging about it up until now, but mostly because I didn’t feel like I could be a respective voice on the topic. I’ve had a number of people encourage me to suck it up and just put something out there. So here it goes…

I want to be upfront that I am doing all of my Rails development on OS-X. As time goes by it seems to be getting easier and easier to do Rails development on Windows, but the premier development environment is still on OS-X. If you are using Windows, I would encourage you to leave feedback (or do a blog post!) on what did and did not work for you. With the exception of a few tools, everything should work just fine on Windows. There is also a great question on StackOverflow that is asking about Ruby/Rails limitations on Windows.

Getting Started

I’m not going to start this post the same way most other beginner posts start, with a sales pitch on Rails or an explanation of MVC. I’m going to assume that you already know why you would want to use Rails, and that you understand the basics of MVC. If not, then there are quite a few good tutorials out there and resources out there.

If you’re on OS-X the first thing you’ll want to do is to get the developer tools installed. This can be done from the OS-X disk, from the App Store (by getting XCode 4), or you can download it from the Apple Developer center if you’re signed up as a Mac or iOS developer. This will install most of the default tools you need to get started. These are things like Git, Ruby, Ruby Gems, etc…

At this point it might not be a bad idea to run this command in Terminal:

gem update --system

This will just make sure that you are running on the latest version of RubyGems (more on that later).

Using RVM

The second step is to go grab and install RVM (Ruby Version Manager). Ruby Version Manager is exactly what it sounds like, it lets you install multiple versions of Ruby and also multiple sets of gems. This might not mean much to you right now, but it will, and you’ll be thanking some deity later on that you have it. Trust me, you want to do this now.

It is a bit obtuse, but all it is doing is downloading and executing a script which will install RVM for you. If you want to look at the script, just execute the part inside of the parentheses and it will download and display the script in the terminal.

Once that completes, you just need to follow one more basic step to get RVM working, and that is to add a little chunk of code to your bash profile. In many places, including the RVM site, it says to add this code into your “.bash-profile” or “.bashrc” file in your home folder. Well, on my Snow Leopard machine it is just called “.profile” and let’s look at how we can add code into it.

In case you aren’t bash saavy, you can just change directories to a tilde to get to your home directory easily.

cd ~

In order to see your hidden files (file prepended with a period), just run this command:

ls -a

On OS-X, if you only have default tools installed, just run this to edit your profile in TextEdit. (Or if you have TextMate run ‘mate .profile’, or Vi run ‘vi .profile’ etc…):

This will allows RVM to load into your session, if you’re wondering why this is needed you are about to find out. If you run into any troubles, just head over to the RVM installation page and check it out, they have some troubleshooting tips.

Now that RVM is installed, close your terminal and restart it. This should allow RVM to load itself into your session. Go ahead and run the following command to make sure that everything was successful:

rvm notes

It should print some notes out for your platform. The next thing we can do is ask RVM what versions of Ruby it knows about:

rvm list known

You should now see a list of Ruby versions that RVM knows about. In order to install a version of MRI (the original Ruby runtime), you can just specify a version:

rvm install 1.9.2

The code above installs the latest release of Ruby 1.9.2 (at time of writing is 1.9.2-p180), but if you want to install Ruby 1.8.6, just replace the version number. If you don’t know which version you want, then you probably want 1.9.2. You can also set 1.9.2 as the default by running this command:

rvm --default use 1.9.2

And since RVM is all about being able to run multiple rubies, you can install as many as you want!

You should have RVM all installed and setup now. You might be thinking, what the hell was all that about? Well, you’ll find out in a bit.

Due to some comments below, I realized that I made a bad assumption about how RVM works. So the following part has been slightly rewritten, thanks Scott!

Creating the Application

I’m going to call this site ‘rails-baby’. Put it in your home directory wherever you want, I usually put mine in a “Dev” folder under my Documents or something. But the first thing we need to do is to create a gemset for our application. We can do this by running the command:

rvm use 1.9.2@rails-baby –-create

In order to get started, we need to get the latest version of Rails on your machine (3.0.5 at time of writing). I’m not going to explain the command below just yet (we will talk about gems in a bit), but suffice to say it will install Rails into your gemset for you:

gem install rails

This will take a bit. Now that you have Rails installed in your gemset, we need to create a new application.

So once I’m in my “Dev” folder, I’ll run:

rails new rails-baby

This command creates the folder and writes a bunch of stuff into it. You now have a real working Rails app. As I was saying before, we will now get RVM hooked up into our app. So I just go into the directory we just created:

cd rails-baby

Now that I am in that directory I am going to create what is called an rvmrc file. This file is where the magic of RVM comes in, since we are in our project directory, we can run this command:

rvm use 1.9.2@rails-baby --rvmrc

And this is going to create a file called “.rvmrc” and place the string “rvm 1.9.2@rails-baby” into it. The command in the files tells rvm to use Rails 1.9.2 and to use the gemset called “rails-baby”.

Gemsets, Your Wonderful Friends

What is a gemset? Well, I’m glad you asked. A gemset is just a set of gems. What is a gem? Well, there is a tool called RubyGems which allows you to download and install “gems”. Gems are just projects packaged up in a way that allows you to easily download and install them. The problem is that RubyGems operates in a global way. If I go to a command prompt and type “gem install mygem” then it will install “mygem” into my local RubyGems directory, and then any Rails application I am using can access it. Similar to how we installed Rails earlier.

This sounds great at first, until you realize that this is pretty hard to manage. You might have multiple gem versions in different projects. Or one project might have a gem that needs a specific version of another gem. Or you might have a gem that works on one version of Ruby, but not another. The list goes on and on. Wouldn’t it be great if we could have gems, but specific to each project? Yes, that would be great, and that is exactly what RVM does!

Let RVM Do Its Magic

Now that we have created the .rvmrc file, change directory into the current directory to get RVM to pick up the file by running this command:

cd .

You should get a warning that RVM has picked up a new .rvmrc file and asks if you want to trust it. You’ll have to tell it “yes” or “no”, but in this case, we just created this file and so you want to trust it. As the warning states, whenever you cd into this directory, RVM will execute this file which will change your current version of Ruby and your current gemset. Pretty sweet!

Make sure that your gemset is selected by running:

rvm gemset list

If there isn’t an arrow next to your gemset, then just change directories to the current directory again, or cd directories up one level “..” and then back into the rails-baby directory. This will cause RVM to make the gemset active.

You could theoretically just install gems into it now using “gem install whatever”, but you don’t really want to do that just yet. In Rails 3, it is convention to use a tool called Bundler. Bundler allows you to easily track and version the gems which are required by a particular project. Think of RVM as the peanut butter, and Bundler as the jelly. They are both much better when used together.

In order to use Bundler, we will need a Gemfile to put all of our dependencies into. Thankfully Rails 3 creates one for us when we create a new application. The file is called “Gemfile” and is in the root of the application. If you are using TextMate (like me, since I am lame and don’t use Vim), you can just open the entire project folder from the GUI (or by running “mate .” while inside your project folder). Rails is entirely folder based, so there isn’t a project file to open or anything.

Inside of the Gemfile you will see a bunch lines that looks like “gem ‘rails’, ‘3.0.5’” and others that are commented out. The lines in this file tell Bundler what gems to install. And if you are using RVM, then the gems get installed into your project’s gemset! Pretty awesome, huh? Yep, but first we have to get Bundler in order to run our Gemfile. So we just do this:

gem install bundler

You can avoid having to do this by adding bundler to your global gems within RVM by adding it to the ~/.rvm/gemsets/global.gems file. Now that we have bundler installed, we have to tell it to install the gems in our Gemfile. To do this we just run this command:

bundle install

You’ll get used to running this command pretty often (you can just shorten it to ‘bundle’ if you don’t want to type ‘install’), because anytime you add a dependency to your application, you just add it to your Gemfile and run “bundle install” to install it.

Bundler works in some really cool ways, and does some neat stuff in order to make sure that your library versions don’t change when moving between machines and environments. If you are interested in reading about how Bundler works with lock files, versions, groups, etc…, I would recommend heading over to the “Understanding Bundler” page on the Bundler website.

You’re Almost There

At this point you are almost ready to really get started. You have installed RVM, Ruby, Bundler, Rails, and you have created your first project. Phew! That sure was a lot of work! The next time you do it though, it’ll take you about 1 minute and you’ll just breeze right through it. It really will become second nature.

At this point though, I don’t want to end this post without you having seen your working website! All you have to do is run the command:

rails server

And then open your browser to http://localhost:3000. You’ll see the default “Welcome aboard” page in your browser, and you can be proud that you are now running a Rails application! You can also shorten the command to just “rails s”. If you want to see all of the commands that rails provides to you, just run the “rails” command when inside of a Rails application folder.

Before I leave you though, I want you to go into your application and look in the “public” folder and find index.html. This is the static page that you were seeing when you opened your browser, Rails just feeds this page up by default. Don’t you feel cheated? Well, if you don’t, you should! Delete this file out, and then reload your app. Now you’ll see an error that says “Routing Error – No route matches ‘/'”… now you’re really running a Rails app!

In The Future

Now that we have a Rails app setup, the next step for us is to start to add some dependencies and some additional functionality to it. We will look at how to get our routes working, so you can get rid of that nasty error, and we will look at getting some tests up and running. Then after that we will just continue to add functionality to the application, pulling in what we need as we go.

Your Part

And what I need from you, dear reader, is feedback. Am I missing pieces? Am I doing things in a silly way? Am I the best thing since sliced bread and you just want to shrink me down and put me in your pocket? Let me know!

34 comments

Very good tutorial Justin. I was lucky enough to work on my first two rails projects recently and this is all helpful advice for setting up your environment to start your project.

What may be helpful for another post is an explanation of the rails console and debugging applications made with ruby. Did you find ActiveRecord difficult to wrap your head around with all of the class level methods? It just felt so wrong to me, coming from C#.

Good intro into Ruby on Rails, Justin. I have purchased Rob Conery’s TekPub series as well where he spent the first session of explaining the setting up the tools. I need to invest in a few books , including the ones you mentioned up there. Good call.

I have been dabbling with ASP.NET MVC for a few years now, and especially liking the power of “code-driven” scaffolding, rake and migration of Ruby/Rails. I think you will touch that in the upcoming series. I purchased RubyMine 3.1, and looking forward to using the IDE.

In my case, I installed and setup in environment on Ubuntu 10.10 a few times (using VMWare and native install). It is not for the faint of heart, and once you are up and running, you are in total control.

Here in MN, there is a very friendly dynamic user group, RubyMN which I just joined. http://www.ruby.mn/.

Overall, a nice post. Looking forward to reading future posts. One suggestion for future post, maybe, pick a sample project and walk us through the creating, adding features, authentication, testing, as you see fit. I know that is a lot of work, and applaud your effort in putting out there. Kudos to you.

@Tyler Thanks! And yes, I am definitely going to touch on the Rails console and debugging Rails applications. As far as ActiveRecord goes, are you talking about how you wire it up? I haven’t had too much trouble with it, but that was also one of the things that I focused heavily on back in the day. It hasn’t changed much in Rails 3 with the exception of the query syntax.

I think that coming over to Ruby/Rails from C# and .NET is going to be a big jump no matter how you look at it. There are vastly different ideas, approaches, and development paradigms going on in the two ecosystems.

Great walkthrough so far! The only thing I would suggest is letting RVM create the gemset and .rvmrc for you. Example:

cd rails-baby
rvm use 1.9.2@rails-baby –create –rvmrc

This one command will create the gemset, create the .rvmrc, and get everything set up for you.

One other suggestion I have is to install rails within your gemset. I’ve run into a lot of situations where I need different versions of rails for each project… so a lot of times I’ll end up doing something like this:

Having been working professionally with Rails for over 4 years now, I’m so happy that you wrote something like this up. All I can say is it has gotten SO much better. Wayne has done a fantastic job with RVM, and he’s also working with Dr Nic at EngineYard to produce Rails Installer, which is trying to make installing Ruby/Rails on Windows painless. I have really gotten to love the Ruby community, and I encourage anyone who’s interested in the language to find a local user group or attend a conference (a few of them are free). And if you’re looking for a job, there’s also huge demand for good Ruby developers.

Looking forward to the upcoming series, Justin. I’ve been tinkering with Rails in my spare time (also a .NET developer by day) and would love to hear how your learning process went / is going. I’m doing my RoR development on a Windows machine right now and haven’t encountered any major issues. The only real pain was picking an IDE since on the Mac side Textmate is pretty much the defacto standard (I ended up going with RubyMine and it has suited my needs).

I’ve been doing much the same thing as you Justin. Our company has decided to move off of Windows on the Server (slowly) so much of our new development is done with Ruby. (Sinatra ATM, but we’re using ActiveModel and ActiveRecord with TinyTDS to connect to SQL Server.)

I just finished working through and reading “Crafting Rails Applications” (http://pragprog.com/titles/jvrails/crafting-rails-applications) which as an experienced C# developer I would say is the single best way to go about learning Rails’ internals in a short time. I have been reading The Rails 3 Way which is a great reference even if there is large overlap with the online API docs. Separate from Rails I would strongly suggest “Eloquent Ruby” (http://www.amazon.com/Eloquent-Ruby-ebook/dp/B004MMEJ36) which is hands down one of the best tech books I’ve read. (Additionally because the number of single line code examples is not huge the book works very well in the cheaper-than-PDF cost of $16 on Kindle.)

The best part of this entire list is the “cheat” gem – if you get stuck on something (like figuring out migration syntax) – rather than hit Google, just “cheat migrations” – and BAM – an entire cheatsheet for migrations will appear in your terminal :)

@Rob: I like the idea of having the Rails gem in the gemset for each specific app. It makes it much easier to use newer versions in new apps you create without affecting existing apps on your dev machine.

@Rob I’d rather have 100 gemsets with 100 different Rails installs honestly. I guess I just feel like the global gemset is the gospel, and probably the only thing I’d put in there is Rake (which RVM does by default).

Hard drive space is cheap, and I’d rather have exactly the right Rails version in my project’s gemset and upgrade it when I’m ready. I guess it’s just a personal preference.

Great start to the series! I have been reading books and watching video series but it is cool to hear it from a Microsoft guy who is working through the same challenges. I do wish you would have chosen Ubuntu as your OS since it is a free option for everyone to do Rails dev on.

@Paul Thanks! I think that the only problem you’ll have on an alternate OS is this first entry. Most of the Rails specific stuff should work the same everywhere. And if you are on Ubuntu, most of this should work for you fine with some minor alterations.

1) I used RVM gemsets in the past to isolate projects from one another, but when Bundler arrived, RVM gemsets lost their appeal. Bundler does a perfect job of isolating and managing gems and their versions for a project. In addition, if you run commands from your text editor, you will have to teach it to load the correct gemset (That is, setting the correct gem paths in rubygems environment variables), and that is a major PITA. Gemsets seem like an unnecessary complexity today. Bundler support is built it into Rails 3 and can be used with any non-Rails Ruby project

2) You wrote that Ruby comes from XCode? Really? Well, it’s been a while since I built my dev stack from scratch, but I think there is already a system wide Ruby interpreter even before you install XCode, correct me if I am wrong. But what is even more important is that if you are using RVM, your ruby interpreter AND rubygems come from RVM (~/.rvm/rubies). Run
which ruby
XCode is needed to actually build programs from source

3) After installing XCode and before RVM you suggest to update rubygems. This is completely useless because after you install RVM, each new compiled ruby will have its own rubygems installation. Run
which gem

4) Didn’t you install macports? It’s a port of unix utilities to OS X, you can easily compile MySQL, Postgres, Imagemagick or any other stuff.

@Scott Bundler will manage which version of Rails you’re using – whatever you specify in Gemfile will supercede what’s in global. The thing you DO get is the ability to say “rails new site” without having to create the gemset, install rails, etc.

@Scott @James while it might *seem* like having multiple Rails installs is a good idea – it’s really not (caveat coming). Minor updates are usually security fixes – so it’s generally a good idea to make sure that Rails is *always* at the tip.

The caveat is, of course, with major versions. But as I mentioned to Justin yesterday – if you’re running Rails 2 you’ll be using 1.8.7 – which is a whole different Ruby and therefore a whole different gemset.

Either way – Bundler manages your gems; you’ll have the version you need per app anyway.

Interested in your thoughts around the SOLIDness of common rails/ruby practices.

For example, as Tyler mentions, it is common for rails controllers to maintain concrete dependencies on AR models.

I think this stems from the fact that anything is fakeable in ruby, however it still seems like poor design to me. (Need a caching layer on one of your endpoints? There goes your open-closed principle.)

In my last project I rejected this practice in favour of DI. Was I right or wrong?

It is common in general for ruby software to reference all sorts of third-party libraries directly rather than as implementation of abstraction. Why?

@Ben I think that in Ruby you have much more flexibility built into the language. Yes, you can fake anything, and you can much more easily use strategies like AOP without using any sort of DI. You can swap out methods at runtime, or replace classes fairly easily. With Ruby there are no discrete interfaces because essentially everything is an interface. Since you don’t have types, you only care what messages a class responds to.

If you think about how you test in Rails, you’ll see exactly what I am talking about. Let’s say in .NET I wanted to stub out a “find” call to the database. I would need to abstract my repository behind and interface, and likely inject that into a service. When I am testing, I would then mock that interface and pass the type in. With Ruby, I don’t have any interfaces, I just simply pull in whatever mocking framework I want and tell it to replace all calls to “find” on *any instance* with some chunk of code. I don’t need any interface because I can simply replace the behavior.

My point is that the coincidental testability that Ruby’s open classes provide arguably encourages poor design. Perhaps the testability of ruby programs is more often a language side effect rather than a product of good design.

What about the design you’re left with? How decoupled is it? How reusable is it?

Notice in your example you didn’t employ TypeMock, that’s because you’re happy with the decoupled design you get as a result of introducing those seams.

@Ben I think that in the Ruby world, design is often prescribed by the framework more so than on other platforms. In this case, the patterns that are frequently used by Rails are predictable and known to be testable. To stray outside of the patterns established by the framework puts you on your own, and you should probably have a good reason for doing it.

On the other hand, I think that the Rails world has not put as big of an emphasis on application design as other platforms, and it is in large part due to the fact that they have more consistent patterns than other platforms, and because one size does not fit all like many people seem to believe.

And as far as things being “decoupled” and “reusable”, well, I think that discussion opens an entire can of worms that I don’t have time for right now.

Finally I’ll say that I have seen some articles around the web where some people are starting to advocate for using service classes in Rails, since putting operations on models, in helpers, or inside of controller actions is often not ideal. I think most of the patterns translate to some extent or another, and you should just carefully pick and choose what works for you.

@Rob Gemsets serve more purpose for me than bundler. In the last major release, you’re probably right. Most Rails 3 devs are likely using 1.9.2, and most Rails 2 devs are likely using 1.8.7 (or ree), however I’m willing to bet that won’t be the case in Rails 3.1… and then my default “rails” script is screwed up for my sites that aren’t updated if I put rails in my global gemset.

I am following your tutorial and have encountered an issue with the installation of RVM. When I issue the command “bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )" it gives me an error: "bash: line 1: html: No such file or directory
bash: line 2: syntax error near unexpected token `<'
'ash: line 2: `301 Moved Permanently”

The biggest problem for most people coming to Ruby (or Python, for that matter) from a language that uses a fused, compile time static typing model (Java, C++ and C# or more or less examples) is the “duck typing”
concept.

For starters, it would help, IMO, if we didn’t call it duck typing! What it really is, is an “Abstract Type”, ala “Abstract Data Typing”, but with a twist: “Abstract Semantic Typing” (AST).

So, the type of an object is *utterly* independent of its internals, static class name, and to a certain extent its inheritance hierarchy.

Think of AST as, at the concrete level, the signature AND externally visible semantics of a set of one or more methods, and you’ll start getting there.

Ideally, Ruby would have a way of grouping messages into ASTs, and in point of fact, I suggested just that some time ago, because once an AST has been created, then testing becomes semantic testing (any object that responds to a given AST should be testable using exactly the same black box tests).

Since this kind of grouping does not yet exist, and probably never will, it helps to modify the way you do OOA by thinking about each application you are designing as a domain specific language (DSL), then designing the code to allow you to “speak” this DSL.

I wanted to comment that a year later, this still holds up. The differences for me: RailsInstaller.org is *amazing* for Windows. It’s stupid painless to have rails now. I don’t use RVM but I’ve yet to come into the need. Starting on Rails 3.2.x now is seamless. I have RubyMine 4.5 which is awesome but Aptana Studio for Eclipse is almost equal. Both run perfectly fine on Windows despite people despising the OS in the community.

Within a week this tutorial specifically was no longer applicable but it took a little bit of growing pains to understand it. I’m finding that for every manual methodology someone seems to mention a command that circumvents a ton of work. Rails is incredibly deep on its own, much less each gem involved. It’s almost overwhelming coming from .NET land but it’s worth the knowledge. I can’t remember mentioning this phrase before, ever: I’m excited to learn Rails.