Skip to content

Meetup notes: Tuesday Feb. 7, 2012 at Blazing Cloud

rutipo edited this page Feb 8, 2012 · 8 revisions

Not rely on scaffold to create the view.

Rails is based on the model view controller architecture.

Model: business logic and data.

View: how the model is presented.

Controller: facilitates interaction between model and view.

$ rails new book_project

Creates a new app in a folder with the name book_project.

$ cd book_project
$ bundle install

$ rails generate model Book title:string author:string

$ rake db:migrate

Look in the directory. There's a book.rb model file, but no book controller or book views (like you'd get if

Now we'll create a new controller for the book. Create a new file in app/controllers/ and name it books_controller.rb ! Note the plural. (Model names are singular, while controller names are plural.)

class BooksController < ApplicationController end

That's our controller file. It's a new class It doesn't have any actions in it. The first thing we'll define is a method for the index page. Usually, the index page lists all the stuff in that model.

By the way, to see what routes we have available in our app, run this: $ rake routes Right now, if we run that, nothing happens. That's because we have no routes mapped in config/routes.rb!

Now, open up config/routes.rb and add this line: resources :books

So it looks like this: BookProject::Application.routes.draw do resources :books end

Just adding the ''''resources :books'''' line creates all these routes! Type $ rake routes again and see all your new book routes. What ''''resources :books'''' does is define these new routes: GET /books/index.html GET /books/edit.html GET /books/new.html

DELETE /books PUT POST

However, this is not the IMPLEMENTATION. If we go to localhost:3000/books, it says "template is missing" instead of route doesn't exist. (In production, it'll be a 404).

There's a pattern that's implemented: there's a whole set of five different URLs that are the standard REST URLs. So Rails has codified that, becuase it's convenient if everyone uses the same patterns. So you just have to know: new, edit, and so on. Q: how does it know? A: books is an arbitrary word, that is, by convention, the pluralized name of your model. You COULD name your controller foobar, but if you do name it the pluralized name of your model (like books), it'll look for a model named the singular version (like book).

Now go into app/views/ folder. Create a new folder called books to hold the book views. In app/views/books, create a new file named index.html.erb and put this in it:

Books

Now go back to localhost:3000/books and you'll see that it picks up our new view (yay!) and renders whatever it finds, which for now is just a title that says "Books" =) But waht we really want is a page that displays all our books. So now we'll modify our controller so that it knows to send it a list of books. Go to /app/views/books/index.html.erb and make it look like this:

<h1>Books</h1>
<table>
  <tr>
    <th>Author</th>
    <th>Title</th>
  </tr>
  <% @books.each do |book| %>
  <tr>
    <td><%= book.title %></td>
    <td><%= book.author%></td>
  </tr>
  <% end %>
</table>

Everything inside of <% and %> is ruby code, embedded in our html! @books is our list of books. For each object in that list, display the author and title.

$ rails console
> book = Book.new(:author => "Steinbeck", :title => "Grapes of Wrath")
> book.save

Now go back and refresh and it shows up.

class BooksController < ApplicationController def index @books = Book.all end

  def new
    @book = Book.new
  end
end

Now, we'll create app/views/books/new.html.erb

New Book

<%= form_for(@book) do |f| %>
<% end %>

Now go to book/new and we hit the page. But our form is empty right now. So we'll add fields to our form!

In app/views/books/new.html.erb:

New Book

<%= form_for(@book) do |f| %> <%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :author %>
<%= f.text_field :author %>
  <%= f.submit %>
<% end %>

Test it out. Try making a new book, and you get: ''''Unknown action. The action 'create' could not be found for BooksController''''! You can see it in the server log, too. So now, we'll go and make the create method in app/controllers/books_controller.rb

class BooksController < ApplicationController def index @books = Book.all end

  def new
    @book = Book.new
  end

  def create
    @book = Book.new(params[:book])
    respond_to do |format|
      if(@book.save)
        format.html {redirect_to :action=>'index'}
      else
        format.html {render :action=>'new'}
      end
    end
  end
end

Now let's try saving our book again. Back at localhost:3000/books/new ... make a new book, then it should redirect you back to the index page and you'll see the new book!

What's respond_to? It's the response to the post request. You can have different types of format like json and xml. Here, we have an html page, so we want the html to be rendered.

Q: What's the best way to see the names of all the methods we need? A1: api.rubyonrails.org -- Rails API documentation. A2: or, if you know the method name, you can check in the console: ri (method name)