Rails 3 Baby Steps – Part 2

Go here if you want to see an index for the entire series.

In the last part of my series on Rails 3, we got up and going with Ruby, RubyGems, RVM, and finally Rails. It may have seemed like a lot of overhead to get up and running, but keep in mind that RVM only needs to be setup once on your machine, then you can use it on as many projects as you would like.

In this part I want to create a single static vertical stripe in the application. We are going to do this by creating a route which will map to the root of our website. We are then going to use the rails executable to generate a controller and some views to go with our route. In this post we are going to focus entirely on getting the entire pipeline running, but without a database at this point.

If you’ve used Rails before, then you probably know that it is big on convention. Everything has a default place, and the project structure is no exception. If you were to open up your project folder, you’ll see this:

image

Sure is a lot of directories! For now, let’s just focus on three of these folders:

  • app – This is where the code for your application is going to go.
  • config – This is where your configuration is going to go.
  • public – This is the website itself. All of your static assets will go here.

If we look inside of our config folder, we will see this:

image

At the bottom you’ll see a route called “routes.rb”. Guess what goes in there! This is where all of our application routes live. The routing DSL in Ruby is very powerful and expressive, but let’s just start off with a very simple example in order to get that nasty error to go away (you know, the one that we had at the end of the last post in this series).

If you scroll down in your routes.rb file, you will see a commented line that starts with “root”. There are a lot of comments in there, so if you don’t see it, no worries. What we are going to do is to create a route which is going to map to our domain (the root of our site). This way, when someone hits www.your-domain.com, they will be routed somewhere.

So, let’s go ahead and leave the root route the way it is, but uncomment it:

root :to => "welcome#index";

And so now when you refresh your website (just run “rails s” if you shut down your server) you should see the error “uninitialized constant WelcomeController”. That should give you a bit of a hint about the route syntax that we entered above.

The “welcome” that you see on the left side of the hash sign is the name of the controller. This is why Rails is looking for a “WelcomeController”. The “index” on the right side is the name of the action. So we need to provide it with a “welcome” controller that has an “index” action…instead of just standing around, let’s make this happen!

Creating The Controller

Remember in the last post when I said that you can run the “rails” command and it will show you a bunch of commands that you can run? Sure you do. Well, if we run it again we will see that there is a command called “generate” which we can shorten to “g”. So if we run this command:

rails g

We will get another list of commands. Guess what this command does? Oh yeah, it is generating application content. In our case, we want to generate a controller. But we don’t really know the syntax. So let’s run this command:

rails g controller

And voila, it shows us further options and gives us usage examples. Isn’t Rails just so nice and helpful? Can you guess what our command is going to look like?

rails g controller Welcome index

This command tells rails to generate a controller named “Welcome” with a single action named index. In reality though, it’ll generate far more content, like this:

image

Whoa! What is all of this? Well the first thing it generated is the controller, and it placed that into “app/controllers”. Again, this is all based on convention. Notice that the controller filename is “welcome_controller” and the class name is WelcomeController. Again, convention. Rails will find and load this controller based on these conventions.

The next thing it generated is a route which is hardcoded to “welcome/index”. This will get spit into your routes.rb file, and you can either ignore it or remove it. The next line you see is “invoke erb”. This line is telling you that it is invoking the erb generator in order to generate the next two files (the generators are pluggable!). In case you are unaware, erb is the name of the default view engine in Rails. As with most tools in rails, you could swap this out for an alternate like Haml.

Next you’ll see it is generating some tests with “test_unit” (which we will be swapping for RSpec in a later entry). Next you see it is spitting out a helper, and finally a test for this helper. At this point, go ahead and refresh your app. You should now see a view rendered in your browser! Woot! You are now an official Rails developer, time to update that resume!

Just kidding. Sit down.

The Controller

First let’s go check out the controller. Open up your app in your favorite text editor and go to the “/app/controllers” folder and open up the “welcome_controller.rb” file. What is in there is pretty terse. It is exactly what we told it to generate:

class WelcomeController < ApplicationController
  def index
  end
end

Okay, so we have our controller class, which descends from ApplicationController, and it has one method in it called “index”. The root of our site is getting mapped to “welcome#index” and so we know that we are looking at the right controller and action. So how does it know how what to render? Well, convention rears its head again.

The View

Go back and look at your app’s folder, and go into “/app/views”. In there you will see two folders. One is called “layouts” and the other is called “welcome”. You have probably guessed that the “welcome” folder contains views for the WelcomeController, right? And I bet when we open that up, we are going to see something with the name “index”. Go ahead, open it up!

Yep, right there is a file called “index.html.erb” and in this file is a tiny chunk of html:

<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>

Okay, so this is the text which is rendering in the browser, go ahead and change it and refresh the page, just so you believe it.

<h1>Rails Baby</h1>
<p>Where babies go to learn Rails.</p>

Sweet. But that isn’t an entire web page, where is the rest coming from? Again, you might have guess that the layouts folder you saw inside of the views folder might have something to do with it. Let’s go look and see what is in there.

The Layout

There is a file in there called “application.html.erb” which just happens to be the root “layout” for our application. If you look into this file, you’ll see that all of the missing html is located within this file. You’ll also see a few default code blocks that are included in this file as well, but the one that we are going to pay attention to is this one:

<%= yield %>

If you’ve used Ruby before, then you may be familiar with the concept of “blocks”. They are essentially chunks of code that you can pass to a method. In order to invoke a block that is passed to a method, we use the “yield” keyword. This works in essentially the same way. When a view is to be rendered, a layout is also selected and then the view is rendered into the layout using the “yield” keyword.

When an erb view is rendered it is usually going to be rendered with a layout. The default layout for an erb view is application.html.erb in the layouts directory. There are ways to change the default layout, and ways to nest layouts, but we won’t touch on those until later.

Assets – JavaScript

You’ve got some nice assets in your project and you want to show them off, right? Ha, right. Anyways, if you check out the default Rails install you’ll see that it uses Prototype by default (this is changing in Rails 3.1). Well, I’m a jQuery man myself, so we are going to need to change this. When we generated our app I could have passed a command line parameter that would have left Prototype out, but that wouldn’t have been fun, would it?

If we look back at our application.html.erb file you’ll notice a tag that looks like this:

<%= javascript_include_tag :defaults %>

This is just a call to the method “javascript_include_tag” passing the symbol “defaults”. If you are new to Ruby this might look weird, but just remember that Ruby methods don’t require parameters. And symbols are kind of like enumerations in other languages, only you don’t have specific set of them, they can be any value.

What we are telling Ruby to do here is to grab us the set of tags that is defined with the key “defaults”. Left as-is this is done way down in the bowels of Ruby, but we can very easily override this. Just go look in your /config folder of your application and you’ll see a file called “application.rb”. You’ll want to get quite familiar with this file, you’ll come back to it pretty often. In this file is where a lot of application specific setup happens.

If you look in the file you’ll see a  line that looks like this:

config.action_view.javascript_expansions[:defaults] = %w(jquery rails)

You’ll want to uncomment that line. What this does is create a set of JavaScript files called “defaults” and uses %w (which splits on whitespace) to reference several JavaScript files. In this case we are referencing jquery.js and rails.js.

Now we have to remove Prototype and add jQuery. Fortunately there is a super easy way to do this. First add this line to your GemFile:

group :development, :test do
  gem 'jquery-rails', '>= 0.2.6'
end

You haven’t seen this syntax before, but what it does is create a group of gems. This just insures that this gem won’t be installed into production, since all it really does is create a helper to install jQuery. Then go to your console and run:

bundle

This will run bundler and install the gem which will create a new generator for you. So now you can execute:

rails g jquery:install

And you’ll see that it will remove all of the Prototype stuff, and add in the jQuery stuff. It’ll prompt you to overwrite rails.js, just say yes! You’ll notice that if you run “rails g” you’ll now see this generator in the console, Rails 3 is super extensible!

The only thing I would do next is delete out the application.js file from your /public/javascripts folder. If this file is there Rails always includes it in your header so that you have a place to put application specific JavaScript. I think it encourages shoving a bunch of random crap into one file, just say no.

Assets – CSS

And finally you’ll see this asset tag:

<%= stylesheet_link_tag :all %>

This is fairly self explanatory, it’ll render all of your css files located in /public/stylesheets into your header. If you need to you can also use expansions in the application.rb file to include stylesheet_expansions as well.

Summary

So now you have seen a very quick example of creating a route, creating a controller and view, and hooking them up together. You also learned how to include your assets into your site so that you can start to build and style your application. In the next entry I am planning on going a bit further and I will create a model along with a corresponding controller and show you how you can start putting data into and pulling it out of the database.

Be Sociable, Share!

16 comments

  1. Note that the jquery-rails gem also adds jquery and rails.js to your :defaults for you, so you don’t need to do that as a separate step if you’re using the jquery-rails gem anyway.

  2. I’m no Rails newbie, so this isn’t exactly for me. I can, however, say that this is quality work and I’d recommend this for anyone starting off. Thanks for contributing this to the scene.

  3. Justin Etheredge

    @Steve Thanks!

  4. Justin Etheredge

    @Evan Always great to hear! Appreciate the feedback.

  5. I’m really enjoying this series. Much of it is a great refresher on some basics that were never properly explained to (or learned by) me, they just sort of fell into practice.
    Thank you, and I hope you continue with part 3.

  6. Thanks for sharing!

    I’ve discovered, that by switching javascript default library to jQuery I had to restart rails server.

  7. Good job. I went through a similar series on my blog when learning. Yours is a better, I think.

    Just wanted to let you know that starting with rails 3.1 release jQuery is going to be the default javascript library so you won’t need to do parts of that, then.

    Good luck on learning RoR more. I can’t wait to read the next part.

  8. Justin Etheredge

    @Buddy Thanks for the compliments! I’m glad you are enjoying the series.

    And thanks for the tip about Rails 3.1, I actually mentioned that in the post. :-)

    Thanks for the feedback, hope you leave more when I publish the next few parts!

  9. @Justin heh, I found it. I think I skipped it in my first read because it was in parenthesis, I do that sometimes which is a bad habit.

    I am really looking forward to your post on rails console, if you do one. That is one thing I haven’t figured out a good way to talk about at all. I kind of have to show people.

  10. Justin Etheredge

    @Buddy Yeah, I’m planning on getting to it. This series is gonna end up being a long one I think :-)

  11. Great tutorial. I’ll recommend for newbies. Good stuff to start.

  12. Thankyou for this… keep it up.

  13. In the current version of Rails 3 uncommenting the ‘config.action_view.javascript_expansions[:defaults] = %w(jquery rails)’ line will result in an error that there is no route to /javascripts/rails.js. The rails.js file has been replaced by jquery.js, jquery_ujs.js and jquery-ui.js and the javascript_expansions line no longer is necessary if you install jquery-rails according to the Github directions (http://github.com/indirect/jquery-rails).

  14. @Denise, it should also probably be noted that in Rails 3.1, jquery.js and jquery_ujs.js are automatically added to your asset pipeline, so you don’t even need to run the generator to make them available.

  15. Thanks Justin, I’m a Newbie in Rails and I stuck with routing, actually I done routing good but I didn’t create the controller, witch you clearly shown in your tutorial, it helped me a lot. I’m looking forward to read your blog.

  16. I’m a newbie and this was very helpful to me. Many thanks for sharing!

Leave a comment