---
# System prepended metadata

title: Week 7

---

# 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