# Week 7
Woah, what just happened?
----
# Project 1 Status Check
- Don't forget to fill out this week's survey
<!-- .element: class="fragment" -->
- Start if you have not done so already.
<!-- .element: class="fragment" -->
- Final Project has been released. Presentation and project due on last week of class.
<!-- .element: class="fragment" -->
----
# Project 2 Release
- Find your teammates
- Submit a project plan
- Meet with a TA next week
----
# Where are we?
- Today marks the end of our core Rails narrative
<!-- .element: class="fragment" -->
![](https://i.imgur.com/XAew2dg.png)
<!-- .element: class="fragment" -->
----
# What's next?
- Today we go over convention, Rails Helpers, and Advanced Modeling
<!-- .element: class="fragment" -->
- Week 8: Gem Showcase
<!-- .element: class="fragment" -->
- Week 9: Making our Webapps even more powerful
<!-- .element: class="fragment" -->
- Week 10: Final Project Presentations
<!-- .element: class="fragment" -->
---
# More on Routes
Why can't we just write english instead of code?
----
# Review: what's in a path?
![](https://i.imgur.com/Ewd2GlO.png)
----
# Review: what's in a path?
* Let's focus on the *resource* part
<!-- .element: class="fragment" -->
* The *resource* can include multiple "_segments_" (separated by `/`)
<!-- .element: class="fragment" -->
* How many segments are in this path?
`/students/10/edit`
<!-- .element: class="fragment" -->
* **Answer:** 3
<!-- .element: class="fragment" -->
----
# Static Segments
- So far we've _only seen_ static segments
<!-- .element: class="fragment" -->
- **Sample Route**: `/students/edit`
- `students` and `edit` are static segments of the route (they don't change, for anyone)
<!-- .element: class="fragment" -->
----
# Dynamic Segments
- Dynamic segments can _be anything_ - they represent placeholders for routes that may pertain to a _particular model_
<!-- .element: class="fragment" -->
- **Sample Route**: `/students/:id/edit`
- `:id` is a dynamic segment of the route - it determines what `Student` we want to edit here
<!-- .element: class="fragment" -->
----
# Example:
* Route: `get '/students/:id/edit, to: 'students#edit'`
<!-- .element: class="fragment" -->
* What are the static segment(s)?
**Static Segments**: `students` and `edit`
<!-- .element: class="fragment" -->
* What are the dynamic segment(s)?
**Dynamic Segment**: `:id`
<!-- .element: class="fragment" -->
* GET Request to `/students/3/edit` would go to `students#edit` with a param `id` with the value 3!
<!-- .element: class="fragment" -->
* All Dymamic Segments get passed in to `params`
<!-- .element: class="fragment" -->
----
# Route Prefixes
- We can gave "nicknames" to routes in order to create _helper functions_
<!-- .element: class="fragment" -->
- **With only static segments:**
```ruby
get '/photos/new', as: photos_new
```
- You can get this path with `photos_new_path` (returns `"/photos/new"`)
----
# Route Prefixes
- **With dynamic segments:**
```ruby
get '/photos/:id/', to: 'photos#view', as: 'photo_view'
```
- You can get this path, _with a model_, using:
`photo_view_path(Photo.first)` (returns what?)
- If `Photo.first` had ID 1 - you can think about this like passing in a hash: `photo_view_path(id: 1)`
- Returns `/photos/1`
<!-- .element: class="fragment" -->
----
# Links, The Hard Way
- **Let's say we have the route:** `get '/photos/new', to: 'photos#new'`
- If we wanted to create a link to one of these routes, use the link view helper
`<%= link_to 'Create a new Photo', '/photos/new', method: :get %>`
- What if the route changes? We have to change all references to it!
----
# Links, Made Easier!
`get '/photos', to: 'photos#index', as: 'photos'`
<!-- .element: class="fragment" -->
- We can refer to this route as `photos_path` in views
<!-- .element: class="fragment" -->
- `<%= link_to 'See all photos', photos_path %>`
<!-- .element: class="fragment" -->
- Much easier and easier to read as well!
<!-- .element: class="fragment" -->
----
# Path Helpers with Dynamic Segments
`get '/photos/:id/edit', to: 'photos#edit', as: 'edit_photos'`
<!-- .element: class="fragment" -->
- This route is named `edit_photos_path` (also, `edit_photos_url`)
<!-- .element: class="fragment" -->
- If we had an instance of a Photo object, we could get the ID from it and use it in the dynamic segment
<!-- .element: class="fragment" -->
- `<%= link_to 'Edit Photo', edit_photos_path(@photo) %>`
<!-- .element: class="fragment" -->
- What is the URL of `edit_photos_path(Photo.first)`?
---
# Convention over Configuration
Who gives DHH the right?
----
# What we need
- 4 core operations on models
<!-- .element: class="fragment" -->
- Create, Read, Update, and Delete
<!-- .element: class="fragment" -->
- 4 GET routes to
1) display ALL objects
2) display a single object
3) show a form to create new object
4) show a form to update an object
<!-- .element: class="fragment" -->
- 3 POST, PUT(or PATCH), and DELETE routes to perform their actions
<!-- .element: class="fragment" -->
----
# Ways to do it?
- Infinite!
<!-- .element: class="fragment" -->
- You can literally structure your routes however you want
<!-- .element: class="fragment" -->
---
#### Rails Doctrine
Optimize for programmer happiness
<!-- .element: class="fragment" -->
Convention over Configuration
<!-- .element: class="fragment" -->
The menu is omakase
<!-- .element: class="fragment" -->
No one paradigm
<!-- .element: class="fragment" -->
Exalt beautiful code
<!-- .element: class="fragment" -->
Provide sharp knives
<!-- .element: class="fragment" -->
Value integrated systems
<!-- .element: class="fragment" -->
Progress over stability
<!-- .element: class="fragment" -->
Push up a big tent
<!-- .element: class="fragment" -->
----
# Convention over Configuration!
`resources :students` creates all the routes for an object named `Student`
<!-- .element: class="fragment" -->
```
get '/students', to: 'students#index', as: 'students'
get '/students/new', to: 'students#new', as: 'new_student'
get '/students/:id/edit', to: 'students#edit', as 'edit_student'
get '/students/:id', to: 'students#show', as 'student'
post '/students', to: 'students#create'
put 'students/:id', to: 'students#update'
patch 'students/:id', to: 'students#update'
delete 'students/:id', to: 'students#destroy'
```
<!-- .element: class="fragment" -->
----
# Resource routing
* Let's talk about `resources :students`
<table style="font-size: 16pt">
<thead>
<tr>
<th>HTTP Verb</th>
<th>Path</th>
<th>Controller#Action</th>
<th>Used for</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>/photos</td>
<td>photos#index</td>
<td class="fragment">display a list of all photos</td>
</tr>
<tr>
<td>GET</td>
<td>/photos/new</td>
<td>photos#new</td>
<td class="fragment">return an HTML form for creating a new photo</td>
</tr>
<tr>
<td>POST</td>
<td>/photos</td>
<td>photos#create</td>
<td class="fragment">create a new photo</td>
</tr>
<tr>
<td>GET</td>
<td>/photos/:id</td>
<td>photos#show</td>
<td class="fragment">display a specific photo</td>
</tr>
<tr>
<td>GET</td>
<td>/photos/:id/edit</td>
<td>photos#edit</td>
<td class="fragment">return an HTML form for editing a photo</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/photos/:id</td>
<td>photos#update</td>
<td class="fragment">update a specific photo</td>
</tr>
<tr>
<td>DELETE</td>
<td>/photos/:id</td>
<td>photos#destroy</td>
<td class="fragment">delete a specific photo</td>
</tr>
</tbody>
</table>
----
# An Opinionated Controller
- index: show all instances of a model
<!-- .element: class="fragment" -->
- show: show a single instance of a model
<!-- .element: class="fragment" -->
- edit: show a page with a form to edit a model
<!-- .element: class="fragment" -->
- new: show a page with a form to create a new model
<!-- .element: class="fragment" -->
- create: create a new model
<!-- .element: class="fragment" -->
- update: update an existing model
<!-- .element: class="fragment" -->
- destroy: delete an existing mode
<!-- .element: class="fragment" -->
----
# Flexible Resources
- We might not want all 7 actions!
<!-- .element: class="fragment" -->
- `resources :students, only: [:show, :update, :destroy]`
<!-- .element: class="fragment" -->
- What routes does this create?
<!-- .element: class="fragment" -->
- Run `rails routes` to see the routes in your project
<!-- .element: class="fragment" -->
----
# Second Look at Rails Generate Scaffold
(Demo)
----
# Pros and Cons of Scaffolding?
- Pro: Quickly build up something from nothing
<!-- .element: class="fragment" -->
- Con: A lot of the base code is going to be replaced anyway
<!-- .element: class="fragment" -->
- You can build your own custom generators to suit your own needs!
<!-- .element: class="fragment" -->
----
# Resourceful Routes Peer Instruction
### True or False
1) The `resources` function creates 7 unique routes for us.
2) Rails builds path helpers for each of our routes to help us link to them.
3) `rails routes` will show us all the routes in our app.
----
# Resourceful Routes Peer Instruction 2
### True or False
1) The `resources` function creates 7 unique routes for us. - True
2) Rails builds path helpers for each of our routes to help us link to them. - False
3) `rails routes` will show us all the routes in our app. - True
---
# Advanced Models
Join Tables, Self-Joins, and Error-Handling
----
# Review
![](https://i.imgur.com/tTkhyLa.png)
----
# Review Cont.
- `customer_id` is a foreign key referring to another tables' id
<!-- .element: class="fragment" -->
- generated using the `references` type
<!-- .element: class="fragment" -->
- `belongs_to` and `has_many` declarations in the model class create helper functions!
<!-- .element: class="fragment" -->
----
# Many to Many Relationships
- What if we wanted to model a school. Two models: Professors and Expertises
<!-- .element: class="fragment" -->
- How do we represent this in tables??
<!-- .element: class="fragment" -->
----
# Join Tables!
![](https://i.imgur.com/2zMwTJE.png)
<!-- .element: class="fragment" -->
- Create a middle man!
<!-- .element: class="fragment" -->
----
# Middle Man!
- `expertises_professors` keeps track of pairs of professors and expertises
<!-- .element: class="fragment" -->
- What does each entry in the table represent?
<!-- .element: class="fragment" -->
- A single expertise that a single professor has
<!-- .element: class="fragment" -->
- If professor Denero had 5 expertises, there would be 5 entries in the expertises_professors table
<!-- .element: class="fragment" -->
----
# How do we do this in Rails?
`rails g migration CreateJoinTableProfessorsExpertises professor expertise`
<!-- .element: class="fragment" -->
- Creates migration to create a join table between two existing tables
<!-- .element: class="fragment" -->
- Let's try it!
<!-- .element: class="fragment" -->
----
# Model Helpers
- Two options for model helper
<!-- .element: class="fragment" -->
- Professor.rb:
<!-- .element: class="fragment" -->
- `has_many :expertises, through: :professor_expertise`
<!-- .element: class="fragment" -->
- `has_and_belongs_to_many :expertises`
<!-- .element: class="fragment" -->
----
# Self Associations
- Consider Employees and Managers
<!-- .element: class="fragment" -->
- Employees belongs_to a manager, but managers are also employee objects...
<!-- .element: class="fragment" -->
```
class Employee < ActiveRecord::Base
has_many :subordinates, class_name: "Employee",
foreign_key: "employee_id"
belongs_to :manager, class_name: "Employee",
foreign_key: "employee_id", optional: true
end
```
<!-- .element: class="fragment" -->
----
# Self Joins
- Facebook! Users have a many-to-many relationship to themselves: "Friends"!
<!-- .element: class="fragment" -->
- Create a join table called "Friendship"
<!-- .element: class="fragment" -->
```
class CreateFriendships < ActiveRecord::Migration
def change
create_table :friendships do |t|
t.references :from_user, index: true
t.references :to_user, index: true
t.timestamps null: false
end
add_foreign_key :friendships, :users, column: :to_user_id
add_foreign_key :friendships, :users, column: :from_user_id
end
end
```
<!-- .element: class="fragment" -->
----
# Model Helpers
```
class Friendship < ApplicationRecord
belongs_to :from_user, class_name: "User"
belongs_to :to_user, class_name: "User"
end
```
<!-- .element: class="fragment" -->
```
class User < ApplicationRecord
has_many :friendships, foreign_key: :from_user_id
has_many :from_users, through: :friendships
has_many :to_users, through: :friendships
def friends
from_users
end
end
```
<!-- .element: class="fragment" -->
----
# Lots of possibilities
- Don't stress about memorizing how to do each of these
<!-- .element: class="fragment" -->
- Focus on the idea so that you can google the "how" when you need it
<!-- .element: class="fragment" -->
----
# Validation Error Checking
- If you try to save a model that doesn't match it's validations, it won't save!
<!-- .element: class="fragment" -->
- No crashes! That's nice...but how do we know what happened?
<!-- .element: class="fragment" -->
```
a = Artist.create
a.errors
```
<!-- .element: class="fragment" -->
---
# In-Class Lab!
https://your.rails.world
----
## Don't forget attendance