You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
panpsychism/ruby_rails_sql_resources/2.neighborhoods_walkthrough.md

262 lines
9.7 KiB

# NYC NEIGHBORHOOD APP - Rails
![](http://stuffnobodycaresabout.com/wp-content/uploads/2013/04/nyc-pc-Broadway-141st-St-looking-north.jpg)
## Walkthrough: Rails CRUD app
We will be making a new Rails CRUD app with a single model called `neighborhood`, with routes, controllers, and views. We will be making much of this manually without scaffolds or generators for controllers and models. This way, you will develop some muscle memory and a greater understanding of each step of the process.
Rails is a framework that favors **convention** over **configuration**, so it is important to name your folders, files, and classes with the correct combination of upper/lowercase letters and plural/singular business.
### 1. INITIALIZE APP
1. Make a new Rails app
`rails new neighborhoods --database=postgresql`
2. **Go into your new directory**
3. Run `bundle install` to install all your gems
### 2. DATABASE AND MIGRATIONS
1. Create your database from the same directory
`rake db:create`
2. Test that the db has been created with `rails dbconsole`.
Then quit the console.
3. Make a new migration:
`rails g migration CreateNeighborhoods`. The g is short for generate, and Create is a rails keyword helper for making migration files for your database. `Neighborhoods` must be *plural* and have a *capital first letter*. There is no space between Create and Neighborhoods. It's `CreateNeighborhoods`.
4. In your sublime in your project folder, open up your migrate folder in your db folder, and you should see a migration file that looks like a bunch of numbers. You will add your model columns and datatypes into this file: A neighborhood should have a name, borough, description, population, and img_url. It should look like this when you are done with it:
```
def change
create_table :neighborhoods do |t|
t.string "name"
t.string "borough"
t.text "description"
t.string "population"
t.text "img_url"
end
end
```
5. Migrate your schema to your database *after* you have entered the information into your migration file. Run the migration with
`rake db:migrate`. This will create a `schema.rb` that you never touch.
**IMPORTANT: Once a migration has run, you never edit your migration or schema file. It is there forever as a record of all your migrations. To edit a migration, you make a new migration to act on the previous one**
Therefore, make sure all your info is correct the first time.
Test that your table has been made by going into the console and typing `rails dbconsole`. Perform a SELECT to test then quit the dbconsole.
### 3. MODELS
1. Create a model. In the app/models folder, create a file called `neighborhood.rb`. It has to be **singular lower case** or it will break.
2. Inside neighborhood.rb make a class called Neighborhood **singular, uppcase N** that inherits from ActiveRecord::Base
3. Seed your database with data for your models, two Neighborhood entries. In db/seeds.rb in your project folder, you can make seeds like the following:
```
Neighborhood.create({
name: "Flatbush",
borough: "Brooklyn",
description: "Founded in 1651 by Dutch colonists, Flatbush consists of several subsections.",
population: "110,875",
img_url: "http://subwaynut.com/irt/flatbushn2/flatbushn215.jpg"
})
```
4. To import your seed into your database, run `rake db:seed` in terminal.
5. Test that your seed worked by going into `rails dbconsole`, performing a SELECT query, and then quit.
6. Test your model by opening up Rails console `rails c`, and querying `Neighborhood.all`, then quit.
### 4. ROUTES
1. In config/routes.rb add `resources :neighborhoods`.
Test your routes by typing `rake routes` in the console. You should get this:
```
Prefix Verb URI Pattern Controller#Action
neighborhoods GET /neighborhoods(.:format) neighborhoods#index
POST /neighborhoods(.:format) neighborhoods#create
new_neighborhood GET /neighborhoods/new(.:format) neighborhoods#new
edit_neighborhood GET /neighborhoods/:id/edit(.:format) neighborhoods#edit
neighborhood GET /neighborhoods/:id(.:format) neighborhoods#show
PATCH /neighborhoods/:id(.:format) neighborhoods#update
PUT /neighborhoods/:id(.:format) neighborhoods#update
DELETE /neighborhoods/:id(.:format) neighborhoods#destroy
```
You can delete all the extraneous comments in routes.rb
### 5. CONTROLLER
1. In your app/controllers folder, manually create a new file
called `neighborhoods_controller`. **The word neighborhoods must be lowercase and plural or the app will break.**
2. Inside `neighborhoods_controller` make a new class called `NeighborhoodsController` that inherits from ApplicationController. **The word Neighborhoods must be plural with an uppercase first letter, and Controller must have an uppercase C**
3. Add the seven methods that correspond to your seven restful routes: index, create, new, edit, show, update, destroy. You don't need to put anything into these methods for now.
### 6. VIEWS
1. In the app/views folder, make a folder for your neighborhoods views. It should be called `neighborhoods` **lowercase plural**.
2. In your views/neighborhoods folder, start by making a view file called `index.html.erb`. This corresponds to your index method in your controller.
### 7. TEST: CONTROLLER -> VIEW
Make an instance variable in your neighborhoods#index controller method. Set it to a string, such as `@test = "America Burger USA 2015 github.com.biz.usa.patty"`.
In your neighborhoods view folder, in `index.html.erb`, write some erb that will display the instance variable: `<%=@test%>`
When you go to access the url `/neighborhoods` in your browser (your index url), you should see the value of `@test` on your screen.
### 8. COMPLETE YOUR CONTROLLER
Fill out your controller. Note that in the example below, variables below are named `@item` or `@items` or `Item`: your app will not have variables called `item`. You will probably want to use `@neighborhood` or `@neighborhoods` and query the `Neighborhood` model.
Note that we are using `strong params` here in `create` and `update` by referring to a private method the restricts the params we are going to make and/or update.
Your `create`, `update` and `destroy` routes will need redirects. These redirects correspond to the prefixes in your `rake routes` with a `_path` appended.
Example using an Item model instead of a Neighborhood model:
```
def index
@items = Item.all
end
def new
@item = Item.new
end
def create
@item = Item.create(item_params)
redirect_to items_path
end
def edit
@item = Item.find(params[:id])
end
def update
@item = Item.find(params[:id])
@item.update_attributes(item_params)
thom waz here-- don't copy-paste code
redirect_to items_path
end
def show
@item = Item.find(params[:id])
end
def destroy
@item = Item.find(params[:id])
@item.destroy
redirect_to items_path
end
private
def item_params
params.require(:item).permit(:gossipgirl, :rupaulsdragrace, :mrrobot)
end
```
## 9. COMPLETE YOUR VIEWS
All of your GET routes will need views. `index`, `show`, `edit`, and `new` are GET routes. Complete the views for `index` and `show`.
- Each item in your `index` should link to that item's `show` page.
- Make forms inside the views that require forms: `edit` and `new`.
- An item's `show` page should have a link to `delete` that item. Put it in `show`.
- Also on the `show` page, provide a link to `edit` that item.
This tutorial gives complete, basic examples of using views, as well as some other useful stuff: <a href="http://tutorials.jumpstartlab.com/projects/blogger.html">Blogger2 Tutorial</a>
## 10. MAKE STATIC PAGES
- Make some extra, static pages for your Rails app. How would you make an `about` or `contact` page?
- Add routing in your `routes.rb`, to tell Rails where to look when certain routes are hit:
```
get '/about', to: 'static#about'
get '/contact', to: 'static#contact'
```
- In this case, we're telling Rails to look in a controller called 'static', and further to look at the actions called `about` and `contact`. Make a controller, call it `static_controller` to handle these static pages. This controller requires no models, migrations, etc. It's just a controller.
- The actions in the controller correspond to the pages themselves. `def about`, and `def contact`. These correspond to views that you will make in a `static` folder or `pages` folder in your `views`.
## 11. EXTRAS
- Set your root to the index.
- Use partials to render your forms.
- Do some very basic styling on your app with css stylesheet in the assets folder.
- Look into a CSS framework like `Bootstrap`, `Skeleton`, `Pure`, or `Foundation`, and implement styling on your pages using one of those.
- Add data validation to your model
- Try out giving your app some JavaScript functionality through the assets folder.
## 12. FIFO / BONUS
#### Make a second model with a one-to-many relationship
Let's expand our neighborhoods beyond NYC, and make a new model called City. A city **has many** neighborhoods. A neighborhood **belongs to** a city.
- Create a migration files for cities.
- In your neighborhood.rb model file, specify this relationship with `belongs_to: cities`
- In your city.rb model file, specify this relationship with `has_many: neighborhoods`
- The neighborhood table will need a column for the foreign key. Run a migration that will add a `t.belongs_to :city` column in your neighborhoods table. This is the foreign key.
- Get it all working such that when you add a new Neighborhood, you specify the city, and can then see an index of cities, wherein you can see each city's neighborhoods.