Ruby on Rails Tutorial, now with more 2.0.2!

April 3, 2008

 
No Gravatar

My first Rails application was the ONLamp: Rolling with Ruby on Rails tutorial, since then Rails has come a long way but I find the beginner resources lacking still. The one thing I’ve learned along the way has been that sample code is invaluable, so today, in celebration of my company’s launch of our completely free online dating (and completely Rails) site Meeta.com, I offer present to you my version of the Rolling with Ruby on Rails tutorial on OSX.

As always, I am not a Rails genius, so my code may not be perfect; if I’ve done something wrong or there is a better, more Railsesque method please let me know. If you find this useful, leave me a comment, I like to know who is dropping in.

Enough of that. Let’s go!

Let’s start by creating our Rails application, if you’re looking for a tutorial on installing Rails check out the Rails wiki on installation.

From your command prompt, type the command “rails bookstore”. By default, Rails will use SQLite as the default database, if you want to use MySQL you will need to run “rails -d mysql bookstore”. This will create a “bookstore” subdirectory contanting a complete tree of folders and files for your Rails application. This is what you should see:

ng:Sites admin$ rails bookstore
      create
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  config/initializers
      create  db
      create  doc
      create  lib
      create  lib/tasks
      create  log
      create  public/images
      create  public/javascripts
      create  public/stylesheets
      create  script/performance
      create  script/process
      create  test/fixtures
      create  test/functional
      create  test/integration
      create  test/mocks/development
      create  test/mocks/test
      create  test/unit
      create  vendor
      create  vendor/plugins
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  Rakefile
      create  README
      create  app/controllers/application.rb
      create  app/helpers/application_helper.rb
      create  test/test_helper.rb
      create  config/database.yml
      create  config/routes.rb
      create  public/.htaccess
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/boot.rb
      create  config/environment.rb
      create  config/environments/production.rb
      create  config/environments/development.rb
      create  config/environments/test.rb
      create  script/about
      create  script/console
      create  script/destroy
      create  script/generate
      create  script/performance/benchmarker
      create  script/performance/profiler
      create  script/performance/request
      create  script/process/reaper
      create  script/process/spawner
      create  script/process/inspector
      create  script/runner
      create  script/server
      create  script/plugin
      create  public/dispatch.rb
      create  public/dispatch.cgi
      create  public/dispatch.fcgi
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/index.html
      create  public/favicon.ico
      create  public/robots.txt
      create  public/images/rails.png
      create  public/javascripts/prototype.js
      create  public/javascripts/effects.js
      create  public/javascripts/dragdrop.js
      create  public/javascripts/controls.js
      create  public/javascripts/application.js
      create  doc/README_FOR_APP
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log
ng:Sites admin$

That’s a whole lot of files! I’m not going to get into details about the directory structure because I’m going to write another blog post about this next time. Very briefly, the bulk of the structure is as follows:

  • app contains your application’s models, views, and controllers…the backbone of your app
  • app/controllers contains all your controllers, these guys handle web requests
  • app/helpers contains helper classes, these will help you clean up code allowing you to keep MVC (model, view, controller) code simple and neat
  • app/models contains all your models, models are the gatekeepers to your database
  • app/views contains all your views, these are display templates we will use to plug in data, which in turn is converted to the final HTML pages your users will see
  • public holds all your publicily accessible files, think public_html

I bet you’re excited already…I was! Let’s fire up the server and see what’s going on. Run, “script/server”

ng:bookstore admin$ script/server
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Ruby version is up-to-date; cgi_multipart_eof_fix was not loaded
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready.  TERM => stop.  USR2 => restart.  INT => stop (no restart).
** Rails signals registered.  HUP => reload (without restart).  It might not work well.
** Mongrel available at 0.0.0.0:3000
** Use CTRL-C to stop.

Now, depending how your hosts are set up, visit your application in your browser:

  • http://0.0.0.0:3000
  • http://localhost:3000
  • http:/127.0.0.1:3000

You should see the default Rails placeholder that looks like this:

01_welcome.jpg

You’ll notice this corresponds with the “public/index.html” file. Well, that’s not too exciting…let’s move on to creating your application. Delete the “index.html” file in your “public” directory, then shut down the web-server, and let’s really play ball.

Let’s think about a bookstore at a high level, and how they really work. A bookstore contains books with titles andthese books each belong to categories or genres. This is the foundation of our application. I’m going to show you how to create a working model, then I’ll explain it. By running the following command, you will create a scaffold for the books in your bookstore with a title and description. Run: “script/generate scaffold Book title:string description:text”

ng:bookstore admin$ script/generate scaffold Book title:string description:text
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/books
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      create  app/views/books/index.html.erb
      create  app/views/books/show.html.erb
      create  app/views/books/new.html.erb
      create  app/views/books/edit.html.erb
      create  app/views/layouts/books.html.erb
      create  public/stylesheets/scaffold.css
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
      create    app/models/book.rb
      create    test/unit/book_test.rb
      create    test/fixtures/books.yml
      create    db/migrate
      create    db/migrate/001_create_books.rb
      create  app/controllers/books_controller.rb
      create  test/functional/books_controller_test.rb
      create  app/helpers/books_helper.rb
       route  map.resources :books
ng:bookstore admin$

Okay, cool, but what is a scaffold? Think of buidings, when builders are working on a new building they put up scaffolds. This allows them to quickly build their building. As their project nears completion, they tear down the scaffolds. When you ran the “script/generate scaffold Book title:string description:text” command you asked Rails to create a scaffold for you. It provides you with a model, the necessary views, and a controller. These scaffolds allow you to quicky and rapidly develop an application, but should not be relied on in a production environment.

Let’s break down the command: “script/generate scaffold Book title:string description:text”

What you’ve done here is created a scaffold for your books, notice though the command says “Book”. ALL models in Rails are singular while views and controllers are plural. This was one of the points that confused me when I started using Rails, so pay attention! You’ll notice “title:string” and “description:text”, these are the corresponding field names and column types, even cooler is that Rails will automagically determine that your “string” is a VARCHAR or your text is TEXT. I used the examples title and description, because they are simple. These could have easily been “quantity:integer” or “isbn:string”.

Now that we’ve created a scaffold with a working model, views, and controller we need to physically create the database. Let’s do this now by running “rake db:migrate”

ng:bookstore admin$ rake db:migrate
(in /Users/admin/Sites/bookstore)
== 1 CreateBooks: migrating ===================================================
-- create_table(:books)
   -> 0.0035s
== 1 CreateBooks: migrated (0.0038s) ==========================================

ng:bookstore admin$

By running this command, you’ve asked rails to “migrate” your database using the “migrations” located in “db/migrate”. Pop in and take a look, but don’t freak out. I’ll explain those at another time. Boot up your server and navigate to your homepage, if you’ve forgotten how to do this just run, “script/server” and visit “http://localhost:3000″. You will likely encounter a “Routing error”, that’s okay though! Later, we will discuss routes, which allow you to control the URL structure.

02_routing.jpg

Remember we created a scaffold for our model “Book”, well, the corresponding controller is located in “app/controllers/books_controller.rb”. Earlier I mentioned that the controller handles all the webrequests. By default, you can access a controller by it’s name, in this case, “books”. Change your browser’s URL to: “http://localhost:3000/books” and you should see this:

03_books-index.jpg

Well, what’s this…no books? Go ahead and add one! Before you get too excited, I want you to pay attention to the URL, notice that when you click “create” you are taken to “http://localhost:3000/books/new” this URL will correspond very closely with your application’s internal workings. .After you add a book, you should see a quick summary of the book you’ve inputted into the database; here’s one that I’ve added:

04_new-book.jpg05_book_created.jpg

Click the back button, and return to the index.

06_books-index.jpg

Wasn’t that simple? You have a basic bookstore where you can create, edit, update, and destroy books from a working database! Take some time to reread this tutorial and play with the application’s internal workings, get familiar with everything here because I will use it as a foundation from this point forward.

If you need the source code, you can download it here.

Was this helpful, do you have questions, or do you just want to bullshit? Leave me a comment! Feel like donating to my beer fund?

Check out part two, “Basic Rail’s routing and a journey into Views, and Controllers“!

  • Rowena
    I solve the problem just add space before the password
  • Rowena
    I got an error in db:migrate, I'm using mysql, is that code ok for mysql?
  • Ben
    Love it, quick and to the point. Great way to start learning Rails.
  • Tom Johnson
    *Big Thumbs Up*
  • I am new on rails, I am trying to find a way to change my table columns and scaffolding fields from within rails. At this point, the only way I know how to accomplish this is to make the changes through MySQL, and then delete the rails helper file before I run a 'generate scaffold' again.

    There must be a more efficient way of doing this. Any suggestions?
  • Gavin
    Tanfastic!

    Great pace!

    Keep 'em coming
  • jefe
    Those with MySql probs:

    MySQL runs on port 3306 by default, so you connection thru the Query browser should be something like hostname: localhost, port: 3306.

    The only account created after installing MySQL is "root" and with no password, I believe.

    "root" is the admin account, so you will have all access

    hope this helps
  • Primate
    This tutorial is simply incredible. You're right, there really aren't many beginners guides, and I was struggling with the concepts of rail (after spending so many years with PHP)!

    Thank you so much :D!
  • oops, i meant i tried to create 'bookstore_development'. I had the right name, it just didn't work out for the reason given above.
  • I downloaded the query browser, and connected to the localhost server on port 3000. I executed 'create database bookstore_database' but I got a 'Access denied for user ''@'localhost' to database 'bookstore_database''. I assume I need to use a username and password, but what should they be? Is there a default set for a hobo app?
  • CJ
    I downloaded the query browser, and connected to the localhost server on port 3000. I executed 'create database bookstore_database' but I got a 'Access denied for user ''@'localhost' to database 'bookstore_database''. I assume I need to use a username and password, but what should they be? Is there a default set for a hobo app?
  • Mike I
    thanks for the tutorial - it was very helpful - i wondered how the scaffold model was implemented in the newest version of ruby ... anyways, i've managed to implement RoR in an XAMPP enviornment on windows, let me know if any one needs help with this implementation.
  • datakix
    digitaln00b,

    ROR 2.0.2 creates a default database reference name for you called 'bookstore_development' in you config/database.yml file.

    If no db exits, then the migration will fail.

    Just open MySQL (via Query Browser) and create a database called 'bookstore_development' and rerun the rake db:migrate command.
  • Can anyone please explain to me why am I getting this error:

    rake aborted!
    #42000Unknown database ‘bookstore_development’

    I've been stuck at this step for hours. :(

    I'm totally new to this.
  • you are, like, my hero and stuff.

    I've been trying to get somewhere with ruby on rails tutorials form various sources and have been pulling my hair out. and feeling very stupid. yours is the first i got to work.

    so far anyways...

    woop woop.

    h
  • Nimit
    pretty good and easy tutorial
  • Froschi
    Great tutorial! Thank you very much.
  • xenfreak
    "Hi,

    finally a tutorial which uses rails 2 AND is suitable for beginners like me. I tried to start with rails, but there are no tutorials that take advantage of the newest version.
    Can’t wait until you post the next entry!!

    Bye"

    i cannot emphasize with this anymore than has already been said. you explain everything clearly, you know exactly what you are talking about, and explain all the minute details.

    you're a great instructor and i look forward to reading more of your tutorials.
  • rails -d mysql bookstore seems wrong to me, I don't know if the syntax has been changed since the writing of this article, but I found the correct order to be

    rails bookstore -d mysql

    With the original script I got a Rails project named -r :)
  • Matt
    Seriously, the one and only rails tutorial I have found that lays the framework for beginners. I really appreciate and enjoyed this tutorial. Thank you so much.
  • Michael
    Thanks for the tutorial. Love it!

    I wish I'd knows about RoR earlier. You can create database interfaces in two minutes with RoR while I'd spent hours creating similar things with PHP. Amazing!

    I'm running OSX leopard and was trying to use MySQL.
    Some trouble I hand with the tutorial and I had to figure out myself:

    Socket file in config/database.yml needed to be changed (for Leopard). Had to change add line of code:

    socket: /var/mysql/mysql.sock

    under "development", "test" and "production"

    I also had to insert password in the given fields.

    Database 'bookstore_development' had to be manually created in mysql
  • Thank you very much. Finally I can make something with RoR. I feel like a kid with a new toy! Sorry, I'm excited.
  • thank you it is good article.
    very important point is using of upstream version of rails.
    keep it up-to-date.. people need it ..
  • iTOtto
    Hi!

    I get the error mentioned by steve, although I did update everything I could imagine:

    macbook-air:bookstore totto$ script/generate scaffold Book title:string description:text
    wrong constant name Title:stringController
    macbook-air:bookstore totto$ rails -v
    Rails 2.0.2

    Any hints would be appreciated...

    Thank you for the great tutorial!
  • SteveJ
    Not really sure why the version of mysql that I'm running doesn't install with innodb turned on by default. Other than that little stumbling block (which was not your issue, but mine) the tutorial was what I was looking for. The other posts which mention tutorials for earlier versions of Ruby/Rails are interesting: usually I can fight my way through version differences . . . not with this stuff.

    Thanks
  • super :D
  • CarniBird
    very nice tutorial
    thanks!
  • Just want to put this out here in case anyone was using postgresql like myself instead of mysql or mysqlite

    I had to make a couple of changes because I was using postgresql. I had to go into the config/database.yml and change the adapter to postgresql and the database to bookstore_dev. These were in the development section. Then I had to rake db:create and then I was able to do the 'script/generate scaffold Book...'
  • Create little tutorial. Helped me get riding the rails quickly!
  • Thank you! I've been wanting to learn Rails for sometime and I've been on Lynda.com for the last week and of course the tutorial for building the web app is using old version of Rails. I stumbled your post - so maybe more people can find this and not have to pull their hair out. I look forward to more tuts!

    Thanks again!
  • Mostanser Billah
    Really wonderful and helpful as well for beginners like me. I was really afraid of starting ruby on rails, this helps me a lot exactly what I want.

    Thanks
  • Thanks for this tutorial. You've really got me started!
  • Jonathan
    Andrew:

    The destroy link has a JS confirmation prompt, which you can disable in the view.

    It's nothing to fault the framework for, the destroy link you see was the result of a scaffold generation, which allows you get get your application up and running.

    If for some reason, you need to run an application that supports non-JS users, of course you will need to make those changes.

    Like I've stated before, scaffolding is meant to assist with development...not replace it. How many skyscrapers or houses do you see, post-production, with scaffolding?
  • Andrew
    Useful tutorial, thanks. I'm still not convinced by RoR though, I turned off javascript and clicked the destroy link next to the new book I made, and nothing happened.

    With javascript on, there is a popup that asks you if you want to delete the book, and that does work. Although the code is inline and quite horrendous.

    I guess this can all be changed behind the scenes, but it stuff like that is so important - why didn't they do it right?
  • Saloni
    oops was too happy to get started with RoR and so skipped the word " nice " in my previous comment...

    newayz here it comes again..

    Nice tutorial Jonathan..Thank you very much for you efforts..
  • Saloni
    Hey tutorial to get started with RoR !!
    Thanks
  • Jonathan
    Yes, you would need to run a scaffold for each model, seperately.

    db:migrate will migrate through all of your migrations, so no, you don't need to run it each time, unless of course you need those fields generated in the database immediately.
  • Ling
    I'm a newbie and trying to get my hands dirty with ruby on rails. So far so good. Question though, if you have multiple models...would you need to run the scaffold one model at a time? Also in the end, do db:migrate for each model or does db:migrate collect all the models at once?


    Thanks.
  • Terry
    Absolute newbie, just installed the latest and greatest rails (read: 2.0.2). After two unsuccessful tries with other tutorials, this was up and running in ten minutes. Well done.
  • Cheri
    Hi,

    I just checked out meeta.com. Nice site! How did you do the routing? The routes look very clean.

    Thanks,

    Cheri
  • st
    Jonathan,
    Thanks for a good tutorial which is relevant for 2.0. I was using the Rails book but had to stop at page 77. because the examples need 1.2.x.
    guess i can go back to the book to complete the depot app.

    st
  • Geoff Wright
    All,

    Great tutorial. Definitely one of the more understandable ones I have read.

    However, one thing I would like to see is the "what next" part. Its great that we can see how to get started, but I'm sooo keen to see how you would move it forwards (adding additional functionality), e.g. letting people register and add books.

    If anybody happens to know of a tutorial that sounds like what I'm after - please, please, please point me in the right direction : )
  • dx111ge
    great stuff, started with RoR but wasn´t aware of the differences between 1.x und 2.x . Now I saw , it works :-) if you use the right tutorial ....
  • nick
    what steps need to be re-run if you add a field to the bookstore? if you wanted to add something like publishing_date, would you re-run the scaffold command? or manually edit the db\migrate01.db file then rake db:migrate again? i have tried what makes sense to me, but couldnt get it working.
  • Anderson
    Hi, nice very nice page..!





















    Good luck !
  • Nice to see Rails2 tutorials are slowly starting to spring up. :)

    Oh, and the last image link is missing "wp-content" in the target url.
  • joey
    Finally I found something that I could do! Thanks!

    I had to do a

    "rake db:create"

    to get the mysql to work (should have set up before).
  • zulfi
    Great post... i have downloaded and installed RoR with aptana IDE. Couldn't understand head or tails of the new framework... this post helped me really to get started...
  • Mitch
    More, more, more stuff like this
  • Sam
    Thank you so much!
    I was pulling my hair out trying to do all the Internet tutorials written for earlier versions.
    .... I hope the books I ordered are up to date.
    Keep up the good work!
  • Mike
    Jonathan really this is the best tutorial I've seen yet
  • Jonathan
    Steve, you are getting an error because you aren't running Rails 2.0

    Try visiting the link to the ONLAMP article I have posted, or updating to Rails 2.0.
  • steve
    When I ran the generate scaffold command I got an error:
    wrong constant name Title:stringController

    What I ran was:

    script/generate scaffold Book title:string description:text

    from within the bookstore directory. Removing all and repeating the above still gave the same result. This is the ruby environment:

    Ruby version 1.8.6 (x86_64-linux)
    RubyGems version 0.9.4
    Rails version 1.2.4
    Active Record version 1.15.4
    Action Pack version 1.13.4
    Action Web Service version 1.2.4
    Action Mailer version 1.3.4
    Active Support version 1.4.3
    Edge Rails revision unknown
    Application root /home/steve/projects/ruby/bookstore
    Environment development
    Database adapter mysql
  • Jonathan
    pritish:

    I have the command to generate a Rails app for use with a MySQL database, maybe I will make it bold so it's clearer.

    As for, rake db:create:all, I've never used it...EVER :P Thanks for posting, perhaps somebody else will have that problem.
  • pritish
    Good metaphors / writing style. However, since I installed RoR with mysql, I had to add a couple commands to make this example work:
    [1.] rails bookstore -d mysql
    script/generate scaffold Book title:string description:text
    [2.] rake db:create:all
    rake db:migrate

    thanks for the posting & good luck with your new ventures.
  • sergey
    please more tutorials! love it!!
  • sergey
    please more tutorials! love it!!
  • chris
    Hi,

    finally a tutorial which uses rails 2 AND is suitable for beginners like me. I tried to start with rails, but there are no tutorials that take advantage of the newest version.
    Can't wait until you post the next entry!!

    Bye
blog comments powered by Disqus