From 5357ae7a54950b4ea83800e43d043c4ecc13752e Mon Sep 17 00:00:00 2001 From: Chris Simmons Date: Mon, 7 Aug 2023 12:19:59 -0400 Subject: [PATCH 1/6] Updates m2m and intro to MVC lessons with verbiage and photo examples, with answer callouts --- .ruby-version | 1 + .../lessons/images/m2m-albums-photos-joined.png | Bin 0 -> 28189 bytes module2/lessons/images/one-to-many-answer.png | Bin 0 -> 21749 bytes module2/lessons/intro_to_mvc.md | 16 ++++++++++++++-- module2/lessons/many_to_many.md | 12 ++++++++++++ 5 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 .ruby-version create mode 100644 module2/lessons/images/m2m-albums-photos-joined.png create mode 100644 module2/lessons/images/one-to-many-answer.png diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..37c2961c --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.7.2 diff --git a/module2/lessons/images/m2m-albums-photos-joined.png b/module2/lessons/images/m2m-albums-photos-joined.png new file mode 100644 index 0000000000000000000000000000000000000000..b99fce765fbdd7ae6c5131e5d0e677d24432fa43 GIT binary patch literal 28189 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

JL`=VQ1WpzvP3evDz)9WpH%+|t2p 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 WTSp_DVp+s!H6=N9*$QbB|NjNA0pJM$ literal 0 HcmV?d00001 diff --git a/module2/lessons/images/one-to-many-answer.png b/module2/lessons/images/one-to-many-answer.png new file mode 100644 index 0000000000000000000000000000000000000000..430fba819f9328859356133d73bfdc27158ed5a8 GIT binary patch literal 21749 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 RA~Ps{c#&nX?M2ZCSZv{EwhVHi-2nvZ{(79mBW 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 literal 0 HcmV?d00001 diff --git a/module2/lessons/intro_to_mvc.md b/module2/lessons/intro_to_mvc.md index 9543a60f..e799a60c 100644 --- a/module2/lessons/intro_to_mvc.md +++ b/module2/lessons/intro_to_mvc.md @@ -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 + +

+

+expander arrowLet’s explore about why the 2nd path above isn’t a good idea. +

+ +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? +
+ +## Checks for Understanding - What does MVC stand for? - What are the "logic responsibilities" for each part of the MVC pattern? diff --git a/module2/lessons/many_to_many.md b/module2/lessons/many_to_many.md index ebe3ff5c..f7c9805c 100644 --- a/module2/lessons/many_to_many.md +++ b/module2/lessons/many_to_many.md @@ -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. +
+

Activity: Diagramming students to modules

+Diagramming students to modules +

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.

+
+ # Many-to-Many Relationships Now, we're going to add playlists to our app. @@ -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. +
+

Activity: Diagramming a many-to-many example (albums to photos)

+Diagramming albums to photos in a many-to-many relationship +

In this example, Albums and Photos are joined by the PhotoAlbums join table.

+
+ # Many-to-Many Relationships in Rails ## Adding Playlists From 5708981856a047878e4c2cf09fd0e4e445be5581 Mon Sep 17 00:00:00 2001 From: Chris Simmons Date: Mon, 7 Aug 2023 12:25:34 -0400 Subject: [PATCH 2/6] Adds further reading resource to mvc in action lesson plan --- module2/lessons/mvc_in_action.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module2/lessons/mvc_in_action.md b/module2/lessons/mvc_in_action.md index 6c991f3f..9f0be67a 100644 --- a/module2/lessons/mvc_in_action.md +++ b/module2/lessons/mvc_in_action.md @@ -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). \ No newline at end of file +### 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). \ No newline at end of file From b34d07fc03460d98a477eb73cabc2de16aa850af Mon Sep 17 00:00:00 2001 From: Chris Simmons Date: Mon, 7 Aug 2023 12:26:01 -0400 Subject: [PATCH 3/6] Removes ruby version file --- .ruby-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .ruby-version diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index 37c2961c..00000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.2 From 45af88fe08ecdd1ab9eabfb051edb879c4b4d018 Mon Sep 17 00:00:00 2001 From: Chris Simmons Date: Mon, 7 Aug 2023 12:38:14 -0400 Subject: [PATCH 4/6] Adds solutions to Grouping and Aggregating lesson --- module2/lessons/grouping_and_aggregating.md | 68 +++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/module2/lessons/grouping_and_aggregating.md b/module2/lessons/grouping_and_aggregating.md index dde3facf..238d4227 100644 --- a/module2/lessons/grouping_and_aggregating.md +++ b/module2/lessons/grouping_and_aggregating.md @@ -568,6 +568,74 @@ 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" + +### 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! + +
+

#1: Length of the longest song

+```ruby + Song.maximum(:length) +``` +
+ +
+

#2: Length of each artist's longest song

+```ruby + Artist.select("artists.*, max(length)") + .joins(:songs) + .group("artists.id") +``` +
+ +
+

#3: Name of the artist with the longest song

+```ruby + Artist.joins(:songs) + .select("artists.name, max(length)") + .group(:name) + .order("max desc") + .limit(1) + .first + .name +``` +
+ +
+

#4: Average length of each artist's songs

+```ruby + Artist.select("artists.*, avg(length)") + .joins(:songs) + .group(:id) +``` +
+ +
+

#5: Name of the artist with the longest average length of song

+```ruby + Artist.select("artists.name, avg(length)") + .joins(:songs) + .group(:id) + .order("avg desc") + .limit(1) + .first + .name +``` +
+ +
+

#6: Names of the three artists with the least amount of total plays for all of their songs

+```ruby + Artist.select("artists.name, min(play_count)") + .joins(:songs) + .group(:id) + .order("min asc") + .limit(3) + .pluck(:name) +``` +
+ + ## Checks for Understanding - What are aggregate functions? Where do they appear in SQL statements? From 24e65a02ec6fb7ecf845442ed2e364c03688ec11 Mon Sep 17 00:00:00 2001 From: Chris Simmons Date: Mon, 7 Aug 2023 12:40:52 -0400 Subject: [PATCH 5/6] Alters formatting of grouping and aggregating lesson and puts solutions at the bottom of lesson --- module2/lessons/grouping_and_aggregating.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module2/lessons/grouping_and_aggregating.md b/module2/lessons/grouping_and_aggregating.md index 238d4227..5c0da08b 100644 --- a/module2/lessons/grouping_and_aggregating.md +++ b/module2/lessons/grouping_and_aggregating.md @@ -569,6 +569,14 @@ 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? + ### 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! @@ -635,11 +643,3 @@ Only use these as references after you've tried the above practice queries on yo ``` - -## 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? \ No newline at end of file From 1ad475624b74c32a8c464e3333a108c05f7d7310 Mon Sep 17 00:00:00 2001 From: Chris Simmons Date: Tue, 8 Aug 2023 09:10:28 -0400 Subject: [PATCH 6/6] Adds CFU quiz links to lessons, adds Multiple Joins lesson to lesson index --- module2/lessons/index.md | 1 + module2/lessons/joins.md | 1 + module2/lessons/joins_2.md | 69 +++++++++++++++++++++++++++++++-- module2/lessons/many_to_many.md | 2 + 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/module2/lessons/index.md b/module2/lessons/index.md index baf998e2..87cd8cc7 100644 --- a/module2/lessons/index.md +++ b/module2/lessons/index.md @@ -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 diff --git a/module2/lessons/joins.md b/module2/lessons/joins.md index e87f7ebe..08edb9be 100644 --- a/module2/lessons/joins.md +++ b/module2/lessons/joins.md @@ -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? diff --git a/module2/lessons/joins_2.md b/module2/lessons/joins_2.md index 06069bea..3cf2aaec 100644 --- a/module2/lessons/joins_2.md +++ b/module2/lessons/joins_2.md @@ -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). @@ -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. + +
+

#1: Unique list of songs that appear on at least 1 playlist

+```ruby +Song + .joins(:playlists) + .distinct +``` +

This query works because of the association on `Song` to `playlists, through: :playlist_songs`. Without this association, the query would look like:

+```ruby +Song + .joins(playlist_songs: :playlist) + .distinct +``` +

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`.

+
+ +
+

#2: Names of playlists that have at least 3 distinct artists

+```ruby +Playlist + .joins(songs: :artist) + .select("DISTINCT artists.*, playlists.name") + .group("artists.id, playlists.name") + .having("COUNT(songs.artist_id) >= 3") + .pluck("playlists.name") +``` +

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.

+
+ +
+

#3: Names of artists that appear on at least 3 different playlists

+ +

This query becomes easier to visualize when you have more data.

+```ruby +Artist + .joins(songs: :playlists) + .having("COUNT(playlists.id) >= 3") + .group(:id) + .pluck("artists.name") +``` +
## 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. diff --git a/module2/lessons/many_to_many.md b/module2/lessons/many_to_many.md index f7c9805c..f39fec83 100644 --- a/module2/lessons/many_to_many.md +++ b/module2/lessons/many_to_many.md @@ -561,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?