Welcome Document
Total Page:16
File Type:pdf, Size:1020Kb
Rotten Potatoes Setup > cd Documents > rails new myrottenpotatoes -T Make sure it completed correctly. Some users have reported needing to install additional items such as: > gem install arel > cd myrottenpotatoes; ls > gedit Gemfile & Add the following lines not in a group (http://pastebin.com/86zGGRVU): # use Haml for templates gem 'haml' # use Ruby debugger group :development, :test do gem 'debugger' end > bundle install --without production > rails server Open a browser & navigate to http://localhost:3000/movies You will see an error Open another terminal tab > rake routes > gedit log/development.log & Keep an eye on this file to see what’s happening in your application. > gedit config/routes.rb & Replace contents with (http://pastebin.com/piLDY4eM): Myrottenpotatoes::Application.routes.draw do resources :movies root :to => redirect('/movies') end > rm public/index.html > rake routes > rails generate migration create_movies > ls db/migrate/ > gedit db/migrate/*_create_movies.rb & Paste (http://pastebin.com/tmSkQX8b): class CreateMovies < ActiveRecord::Migration def up create_table 'movies' do |t| t.string 'title' t.string 'rating' t.text 'description' t.datetime 'release_date' # Add fields that let Rails automatically keep track # of when movies are added or modified: t.timestamps end end def down drop_table 'movies' # deletes the whole table and all its data! end end Perform the database migration as follows. > rake db:migrate You can undo the last database migration with the command rake db:rollback to undo . Open in your editor the class app/models/movie.rb and add the following code: class Movie < ActiveRecord::Base def self.all_ratings ; %w[G PG PG13 R NC-17] ; end end Back in main rails server tab, hit ctrl-c and run > rails console > Movie.all Let’s seed some movies by going to a new terminal window: > gedit db/seeds.rb & Paste the following (http://pastebin.com/hNB7kpWz): # Seed the RottenPotatoes DB with some movies. more_movies = [ {:title => 'Aladdin', :rating => 'G', :release_date => '25-Nov-1992'}, {:title => 'When Harry Met Sally', :rating => 'R', :release_date => '21-Jul-1989'}, {:title => 'The Help', :rating => 'PG-13', :release_date => '10-Aug-2011'}, {:title => 'Raiders of the Lost Ark', :rating => 'PG', :release_date => '12-Jun-1981'} ] Movie.send(:attr_accessible, :title, :rating, :release_date) more_movies.each do |movie| Movie.create!(movie) end > rake db:seed If the previous command fails, you should add the protected_attributes gem to your project. Back at the rail console: > Movie.all > Movie.where(‘id=2’) > Movie.find(4) > Movie.find_by_rating('PG') > Movie.where('release_date < :cutoff and rating = :rating', :cutoff => 'Jan 1 , 2000', :rating => 'G') This allows us to interact with our application and DB and experiment with code without changing our web app implementation. Get out of the console & let’s start building controllers and views for our actions. > exit > rails server If you reload your browser window (http://localhost:3000/movies), you should get an uninitialized constant for MoviesController . In another terminal window: > gedit app/controllers/movies_controller.rb & Paste the following (http://pastebin.com/KGWiEt09): # This file is app/controllers/movies_controller.rb class MoviesController < ApplicationController def index @movies = Movie.all end end > mkdir -p app/views/movies > gedit app/views/movies/index.html.haml & And paste (http://pastebin.com/Bz9fuk34): -# This file is app/views/movies/index.html.haml %h1 All Movies %table#movies %thead %tr %th Movie Title %th Rating %th Release Date %th More Info %tbody - @movies.each do |movie| %tr %td= movie.title %td= movie.rating %td= movie.release_date %td= link_to "More about #{movie.title}", movie_path(movie) Refresh your browser window (http://localhost:3000/movies), and you should see the same list of 4 movies that typing Movie.all gave you in the rails console (with prettier formatting). Now let’s update the generic application wrapper (written in erb ) with one in haml : > rm app/views/layouts/application.html.erb > gedit app/views/layouts/application.html.haml & Paste (http://pastebin.com/0RU47cUy): !!! 5 %html %head %title Rotten Potatoes! = stylesheet_link_tag 'application' = javascript_include_tag 'application' = csrf_meta_tags %body = yield When you reload the page, you should see the page title change from MyRottenPotatoes -> Rotten Potatoes! Check out this screen cast to learn more about how these haml files are used to generate the html source code: http://vimeo.com/34754667 Let’s add the capability to show movie details. In app/controllers/movies_controller.rb , add a show method (http://pastebin.com/TESrHmkk): def show id = params[:id] # retrieve movie ID from URI route @movie = Movie.find(id) # look up movie by unique ID # will render app/views/movies/show.html.haml by default end Now, add a haml view for action show . > gedit app/views/movies/show.html.haml & Paste: %h2 Details about #{@movie.title} %ul#details %li Rating: = @movie.rating %li Released on: = @movie.release_date.strftime("%B %d, %Y") %h3 Description: %p#description= @movie.description = link_to 'Back to movie list', movies_path Click on a movie on the list, you should see some details. Now let’s make the movies view a little prettier by pasting a stylesheet (http://pastebin.com/LsLngdin) into: > gedit app/assets/stylesheets/application.css & If you refresh the movie listings page, it should look more professional. Now let’s allow users to add new movies through the web interface, rather than on the command line. > gedit app/views/movies/index.html.haml & And paste the following line to the end (http://pastebin.com/6wLiit6M): = link_to 'Add new movie', new_movie_path When you refresh the page, you should see a link to add a new movie at the bottom (but it won’t work yet). > gedit app/views/movies/new.html.haml & Paste (http://pastebin.com/eu3DFuMX): %h2 Create New Movie = form_tag movies_path, :method => :post do = label :movie, :title, 'Title' = text_field :movie, :title = label :movie, :rating, 'Rating' = select :movie, :rating, Movie.all_ratings = label :movie, :release_date, 'Released On' = date_select :movie, :release_date = submit_tag 'Save Changes' Add a new method inside the Movie class to app/controllers/movies_controller.rb : def new # default: render ‘new’ template end Now when you click on the link, you should see the “Create a new movie” page. Next we’ll enable the form to create a new movie in our app. > gedit app/controllers/movies_controller.rb & Paste the following code inside the MovieController class (http://pastebin.com/FFgBP1Jy): def create @movie = Movie.create!(params[:movie]) redirect_to movies_path end Add the following line to your app/models/movie.rb file inside the Movie class: attr_accessible :title, :rating, :description, :release_date When you submit the form in the browser, it should now create a movie. Wouldn’t it be nice if the web page showed us a status update that our movie was or was not successfully added? Update the create method in app/controllers/movies_controller.rb with the following flash message (http://pastebin.com/N1n4Pkr0): # in movies_controller.rb def create @movie = Movie.create!(params[:movie]) flash[:notice] = "#{@movie.title} was successfully created." redirect_to movies_path end Now we need to update the haml to get and display the message. > gedit app/views/layouts/application.html.haml & Paste the following if statement inside the body, before the yield command, like this: %body - if flash[:notice] #notice.message= flash[:notice] - elsif flash[:warning] #warning.message= flash[:warning] = yield Remember that haml is VERY fussy about indentation and make sure you are consistent with tabs and spacing. Now when you add a movie, a status message should be displayed. Exercise: edit app/assets/stylesheets/application.css so that flash messages are red & centered. Let’s add the ability to edit existing movies, which will require the following changes: > gedit app/views/movies/show.html.haml & Modify the last 2 lines to be (http://pastebin.com/ZD1y6TYc): = link_to 'Edit info', edit_movie_path(@movie) = link_to 'Back to movie list', movies_path > gedit app/views/movies/edit.html.haml & Paste the properly indented haml code (http://pastebin.com/Uqm1AS8Q): %h2 Edit Movie = form_tag movie_path(@movie), :method => :put do = label :movie, :title, 'Title' = text_field :movie, 'title' = label :movie, :rating, 'Rating' = select :movie, :rating, Movie.all_ratings = label :movie, :release_date, 'Released On' = date_select :movie, :release_date = submit_tag 'Save Changes' Add the following edit & update methods to app/controllers/movies_controller.rb (http://pastebin.com/jdTS5P7Q): def edit @movie = Movie.find params[:id] end def update @movie = Movie.find params[:id] @movie.update_attributes!(params[:movie]) flash[:notice] = "#{@movie.title} was successfully updated." redirect_to movie_path(@movie) end Now you should have the ability to edit movies. But what if we want to delete one? Add the following lines to app/controllers/movies_controller.rb (http://pastebin.com/8ZYbFUcb): def destroy @movie = Movie.find(params[:id]) @movie.destroy flash[:notice] = "Movie '#{@movie.title}' deleted." redirect_to movies_path end And then add a delete link to app/views/movies/show.html.haml (http://pastebin.com/Cr8EXQaH): -# Our Edit link from previous example: = link_to 'Edit info', edit_movie_path(@movie) -# This Delete link will not really be a link, but a form: = link_to 'Delete', movie_path(@movie), :method => :delete You now should be able to delete a movie after clicking on a “more info” link. However, a destructive action like delete should probably prompt the user to be sure they want to take that action. So let’s change that delete link to a button instead (http://pastebin.com/mTXuE5up): = button_to 'Delete', movie_path(@movie), :method => :delete, :confirm => 'Are you sure you want to delete?’ That concludes the chapter 4 walk through of a setting up a sample ruby on rails app from scratch. You should now have a better understanding of how the HW2 skeleton is setup..