Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

B2 Lesson updates - Chris #299

Open
wants to merge 6 commits into
base: gh-pages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 69 additions & 1 deletion module2/lessons/grouping_and_aggregating.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,10 +568,78 @@ Test your understanding by writing queries for the following in ActiveRecord:

1. Write a query to return each artist's name and a comma separated list of all their songs, for example "Talking Heads" would have "This must be the Place, Heaven"


## Checks for Understanding

- What are aggregate functions? Where do they appear in SQL statements?
- What do calculation methods in AR return?
- What does the `group by` statement do in sql?
- Why do we need to include an aggregate function when using `group by`?
- When do we need to join?
- When do we need to join?

### Solutions
Only use these as references after you've tried the above practice queries on your own! Keep in mind that there are multiple ways to arrive at these soultions, so if your query returns the expected output but is different than the query listed below, it's still probably good!

<section class="answer">
<h3>#1: Length of the longest song</h3>
```ruby
Song.maximum(:length)
```
</section>

<section class="answer">
<h3>#2: Length of each artist's longest song</h3>
```ruby
Artist.select("artists.*, max(length)")
.joins(:songs)
.group("artists.id")
```
</section>

<section class="answer">
<h3>#3: Name of the artist with the longest song</h3>
```ruby
Artist.joins(:songs)
.select("artists.name, max(length)")
.group(:name)
.order("max desc")
.limit(1)
.first
.name
```
</section>

<section class="answer">
<h3>#4: Average length of each artist's songs</h3>
```ruby
Artist.select("artists.*, avg(length)")
.joins(:songs)
.group(:id)
```
</section>

<section class="answer">
<h3>#5: Name of the artist with the longest average length of song</h3>
```ruby
Artist.select("artists.name, avg(length)")
.joins(:songs)
.group(:id)
.order("avg desc")
.limit(1)
.first
.name
```
</section>

<section class="answer">
<h3>#6: Names of the three artists with the least amount of total plays for all of their songs</h3>
```ruby
Artist.select("artists.name, min(play_count)")
.joins(:songs)
.group(:id)
.order("min asc")
.limit(3)
.pluck(:name)
```
</section>

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added module2/lessons/images/one-to-many-answer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions module2/lessons/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ layout: page
- [Many to Many Relationships](./many_to_many)
- [SQL and ActiveRecord](./sql_and_active_record)
- [Joins](./joins)
- [Multiple Joins / Advanced AR](./joins_2)
- [Grouping and Aggregating](./grouping_and_aggregating)

## Testing and Debugging
Expand Down
16 changes: 14 additions & 2 deletions module2/lessons/intro_to_mvc.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,21 @@ Controllers should limit their database actions to very simple lookups, or creat

NOTE: For task 2, You should not have to create a new view.

**Let’s also quickly talk about why the 2nd path isn’t a good idea.**

### Recap

<section class="answer">
<h3>
<img class="expander-arrow" src="/assets/images/arrow.svg" alt="expander arrow">Let’s explore about why the 2nd path above isn’t a good idea.
</h3>

When you expose an endpoint (a path / URI) for a given resource, it is a good idea to ensure that path is fully fleshed out and functional. A second endpoint can sometimes be confusing for the end user - they may be left asking, _"Which route is the correct one?"_

Also, if the page that is meant to be served needs to change or the paths need updating, now you have not one path but __two__ to remember to update.

Can you think of any other reasons to limit paths to specific resources in web applications?
</section>

## Checks for Understanding

- What does MVC stand for?
- What are the "logic responsibilities" for each part of the MVC pattern?
Expand Down
1 change: 1 addition & 0 deletions module2/lessons/joins.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ irb(main):001:0> Artist.joins(:songs).where('songs.length > ?', 400)
```

## Checks for Understanding
You can also answer these questions using [this form](https://forms.gle/iTQ8T9FX86uAuq6aA).

1. What are the three types of joins covered today? And, what do they return?
2. What is the SQL query to get a list of Artists who have songs that have been played more than 20 times?
Expand Down
69 changes: 66 additions & 3 deletions module2/lessons/joins_2.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ title: Multiple Joins
## Prerequisites
For success in this lesson, be sure you have reviewed the [Joins](./joins) lesson first.

## Learning Goals
* Identify scenarios requiring multiple `join` statements in a query
* Write ActiveRecord queries that join multiple tables utilizing AR associations
* Explore some drawbacks of using AR associations across multiple joins

## Set Up
Clone and check out the `joins-homework` branch of the [Set List Tutorial](https://github.com/turingschool-examples/set-list-7/tree/joins-homework).

Expand Down Expand Up @@ -152,11 +157,69 @@ The takeaway here is, if we're not careful with our joins, it may result in some
## Further Practice
Try implementing some of these queries on your own. You may want to try writing them out in SQL first, before translating them to ActiveRecord.

* Return a unique list of songs that appear on at least 1 playlist.
* Return the names of playlists that have at least 3 distinct artists.
* Return the names of artists that appear on at least 3 different playlists.
_NOTE_: We recommend adding more songs to your playlists to order to work with a larger dataset! You can try the following:
```ruby
Playlist.first.songs << Song.first
Playlist.first.songs << Song.second

Playlist.second.songs << Song.first
# etc., or feel free to create your own songs and Playlist relationships in your seeds.rb
```

1. Return a unique list of songs that appear on at least 1 playlist.
2. Return the names of playlists that have at least 3 different artists.
3. Return the names of artists that appear on at least 3 different playlists.


### Solutions
Try the above queries in `rails c` or in a project first before comparing against these solutions.

<section class="answer">
<h3>#1: Unique list of songs that appear on at least 1 playlist</h3>
```ruby
Song
.joins(:playlists)
.distinct
```
<p>This query works because of the association on `Song` to `playlists, through: :playlist_songs`. Without this association, the query would look like: </p>
```ruby
Song
.joins(playlist_songs: :playlist)
.distinct
```
<p>Note the multiple joins of `playlist_songs: :playlist` where `playlist` is singular on the right-hand side; this is because within the `PlaylistSong` model, we have one association of `belongs_to :playlist`.</p>
</section>

<section class="answer">
<h3>#2: Names of playlists that have at least 3 distinct artists</h3>
```ruby
Playlist
.joins(songs: :artist)
.select("DISTINCT artists.*, playlists.name")
.group("artists.id, playlists.name")
.having("COUNT(songs.artist_id) >= 3")
.pluck("playlists.name")
```
<p>There are probably other ways to do this query! Remember that AR will order your clauses in the appropriate order for SQL, other than when you're using grouping and aggregating and want to return objetcts instead of hashes. </p>
</section>

<section class="answer">
<h3>#3: Names of artists that appear on at least 3 different playlists</h3>

<p>This query becomes easier to visualize when you have more data.</p>
```ruby
Artist
.joins(songs: :playlists)
.having("COUNT(playlists.id) >= 3")
.group(:id)
.pluck("artists.name")
```
</section>

## Checks for Understanding

You can also answer these questions using [this form](https://forms.gle/PvtCtLcVx7CF2mCWA).

1. When would we want to use multiple joins in a query?
2. What is one hazard of potential over-joining?
3. In your own words, describe the process for creating a multiple-join query.
Expand Down
14 changes: 14 additions & 0 deletions module2/lessons/many_to_many.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ Think about the relationship between students and modules (i.e. "Mod 1: Object O

Diagram what the database would look like.

<section class="answer">
<h3>Activity: Diagramming students to modules</h3>
<img src="images/one-to-many-answer.png" alt="Diagramming students to modules" >
<p>In this example, Modules are the "one" / "parent", and students would be the "many" / "children", since many students can be in only one module at a time. </p>
</section>

# Many-to-Many Relationships

Now, we're going to add playlists to our app.
Expand Down Expand Up @@ -147,6 +153,12 @@ When you're thinking about what to call this table, think about how you're likel

Diagram the DB tables you would need to create a many-to-many relationship between two tables that you think up on your own. Include some example data in your tables. If you can't come up with an example on your own, use Photographs and Albums.

<section class="answer">
<h3>Activity: Diagramming a many-to-many example (albums to photos)</h3>
<img src="images/m2m-albums-photos-joined.png" alt="Diagramming albums to photos in a many-to-many relationship" >
<p>In this example, Albums and Photos are joined by the PhotoAlbums join table.</p>
</section>

# Many-to-Many Relationships in Rails

## Adding Playlists
Expand Down Expand Up @@ -549,6 +561,8 @@ We should now have a passing test. Check your work in development by adding some

## Checks for Understanding

You can also answer these questions using [this form](https://forms.gle/odXSt3MqgVqq1R9RA).

- How is a one-to-many relationship set up in a database?
- What does a join table do? Why would we need one?
- How do we test many-to-many relationships?
Expand Down
6 changes: 4 additions & 2 deletions module2/lessons/mvc_in_action.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,7 @@ For additional guidance, consider the following rules:
- No query logic in your Controllers or Views; this should live in your Models.
- No data formatting in your Models or Controllers; this should live in your Views.

### Further Learning
A completed version of this lesson can be found [here](https://github.com/turingschool-examples/mvc-in-action-7/tree/refactor).
### Further Learning and Review
A completed version of this lesson can be found [here](https://github.com/turingschool-examples/mvc-in-action-7/tree/refactor).

You can review the basics of MVC while completing this exercise using [this lesson](https://backend.turing.edu/module2/lessons/intro_to_mvc).