Homework for 8A

Review

Topics Covered: Putting MVC together; building an API app; taking off the scaffolding training wheels

Conceptual Steps

  1. Visualize what you want your application to store, and what properties it has. In this case, it was stories with titles (strings) and scores (integers)
  2. Think about what you want to do with those things. Common actions are look at them, edit them, delete them—in other words, basic CRUD actions. Other things in this case might be to filter by title, or rank by score. These will become your controller methods.

Coding Steps

For review purposes, here are the list of steps we did today:

  1. rails new reddit_rails
  2. cd reddit_rails
  3. rails generate migration create_stories
  4. Edit the migration file found in db/migrate/2014..._create_stories.rb
  5. Create a story.rb file in app/models and add the code to create a model (something that looks like class Story < ActiveRecord::Base ... end
  6. Create a stories_controller.rb controller in app/controllers (it should have something like class StoriesController < ApplicationController ... end)
  7. Give it the methods you thought about in step 2 above (in our case, we made index)
  8. Create a route for your action in config/routes.rb
  9. Create a view index.html.erb in app/views/stories (you'll have to make a folder called stories). Why do we name it index? Because your action is called index. Rails renders the view with the same name as the action. We'll learn how to change that later.
  10. Now you should be able to see your view in your route. Woohoo only 10 steps!


Exercises

E1: rake db:review

Scaffolding

Why are we not using scaffolding? Why do we not want to use it all the time?

E2: Open Source Democracy

Now we're going to write an app that does what our Terminal code for using the data.gov API did. In d8, start by creating new rails app called petitions_rails. If you've lost the code from before, you can find it here.

Setup

For this app to work, remember that we needed to install the gems 'rest-client' and 'json'. The way Rails manages this is in the Gemfile, stored right in first directory. Right now, it looks something like

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
....
At the end of the file, go ahead and add gem 'json' and gem 'rest-client' on their own lines. Then, back in Terminal, run bundle install. What that does is basically run gem install for each of the gems in the Gemfile.

Models and Migrations (Steps 4-5)

Now we want to think about what models our application is going to need. One of them should be fairly obvious: a Petition model. Go ahead and create that, as well as a migration for it. What properties do we need? What type are they? For example, for the stories example we did in class, we needed a title (a string), and score (an integer).

The Start of an Application (Steps 6-8)

Follow the steps in today's code along, as well as in the exercise above, to create a main page. Maybe you want to add CSS...or maybe not. Your choice! In any case, add a "Show petitions" link that links to /petitions. Create a route that maps that URL to a controller (probably the PetitionsController), and create the necessary action (probably index). Make sure your route in config/routes.rb maps to that controller and action.

Now visit localhost:3000 and make sure your link works. Get it so there are no error messages, and it basically shows an empty page.

Now for Some Actual Logic (All the stuff in the code along, but in the model file)

Our model is going to need a way to get data from the API. To use the gems we installed, we still have to require them. At the top of /app/models/petition.rb, add

require 'json'
require 'rest-client'

Now you have to figure out where all the code we wrote last week goes. But this application is unique: we're not pulling data from our database, but from the data.gov API. We're going to create a get_from_api method that does just that.

# app/models/petition.rb
require 'json'
require 'rest-client'

class Petition < ActiveRecord::Base
  def self.get_from_api
    # your code here
  end
end

What should your code do? You want to get the data from the API, and return an array of hashes that contain all the information that we want. Your code should not puts anything—that's what your view is for! If I were to write pseudo-code, it might look like:

def self.get_from_api
  # Get JSON from API
  # Parse it into a hash
  # Get the relevant fields of the hash
  # Create new stories and save it to the database
  # Return an array of story instances
end

Back to the Controller

Start getting used to this workflow: Rails is a lot of switching between files, putting your code in the right place. Now the index method you created before shouldn't call Petition.all, but instead call Petitions.get_from_api. What instance variable should you store that in?

Lastly, the View (Step 9)

Update your /app/views/petitions/index.html.erb file to render each of the petitions title, body, URL, deadline, status, created and siganture count. But don't let the date be something ugly like 1403920011, use some of Rails' built in methods to make it into something nice!

All in All

Now you should have a website that has two pages: a main page (URL /) that has a link to the /petitions page, and a petitions page (with URL /petitions) that shows the first five petitions on data.gov. Congrats, you've built your first somewhat useful website!!

E3: One for All

Add the UI (user interface) and controller methods to be able to view just a single petition by clicking on it on the petitions page. The URL will probably looks something like /petitions/<petition_id>. (Hint: use a show action.) In order to do this, you'll have to use the params hash. We'll cover this in more detail next week, but for now, all you need to know is that if you define a route with :id where you expect the link to include the id number, the id given in the URL will be available as params[:id] as shown below.

# routes.rb 
# :id is a placeholder where the URL will have a number
get '/petitions/:id' => 'petitions#show' 

# index.html.erb
# the actual petition id is put in the URL, ex. 1
link_to 'Show', '/petitions/1'


# petitions_controller.rb
# the params hash will now have a key :id which has the value of 1
def show
  @petition = Petition.find(params[:id])
end

Your website works, but it always gives us just the last 5 petitions. It doesn't let us filter, or search, or any of the nice things the API allows us to do. Let's fix that.

E4 (Bonus!): Customize

In the same app, add the necessary user interface (meaning HTML/CSS in your views), controller methods and model methods that allow us to search through petitions, filter by status, or see more than 5. Then go sign one of them and participate in America's beautiful democracy.


Projects

The Real Deal: Final Prep

This afternoon, you'll have the chance to share your app idea with the rest of the class. Remember that the goal is to convince people that it's an idea worth two weeks of hard work, so ensure that your presentation outlines a well thought-out app that you're clearly excited about. It's important that you keep it short and sweet, so try to practice with a timer at least once before you present! Finally, think about exactly what visuals you want to show in order to explain your idea and make people love it!

Fueling Consumerism on Rails

We're going to begin the process of translating the project from last week into a Rails application. Each class (Item, Cart, Shopper...) will become its own model, and you'll write the controllers and views for them in time. This will also be a chance to go through the flow of building your own Rails application from scratch, as opposed to a codealong.

In your projects directory, create a new Rails app called shopping (Hint: rails new shopping). As with before, we'll start with the Item class. Use what we've learned about creating resources to make the migration, route, model, controller, and view. It should have a property name, which is a string, and a property price, which is a float. Once you've hooked everything together, verify it's working by visiting localhost:3000/items.

Pretty 'n' Sassy

Sass up your webpage! Use SASS CSS in your app/assets/stylesheets/items.css.scss to make your website pretty (the .scss extension means you can use SASS, much like how .erb means you can use Ruby in HTML). Remember to add styles that apply to all pages (like styles on body or all text, for example) in application.css (which you can rename application.css.scss) and only those that apply to the items page in items.css.scss.

Think...think...

Think about how you might make the Cart resource. Can you foresee any problems? What would you type into the Terminal? Write down the answers to these questions.

To the cloud!

Create a new Github repo for your code, and push your code there. If you forgot how, check back in previous exercises or visit here.