Topics Covered: Putting MVC together; building an API app; taking off the scaffolding training wheels
For review purposes, here are the list of steps we did today:
rails new reddit_rails
cd reddit_rails
rails generate migration create_stories
db/migrate/2014..._create_stories.rb
story.rb
file in app/models
and add the code to create a model (something that looks like class Story < ActiveRecord::Base ... end
stories_controller.rb
controller in app/controllers
(it should have something like class StoriesController < ApplicationController ... end)
index
)config/routes.rb
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.Why are we not using scaffolding? Why do we not want to use it all the time?
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.
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.
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).
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.
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
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?
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!
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!!
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.
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.
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!
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
.
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 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.
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.