Skip to content

Commit

Permalink
complete readme
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuabamboo committed Nov 23, 2015
1 parent 3fc068f commit 5c32203
Showing 1 changed file with 40 additions and 63 deletions.
103 changes: 40 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,110 +56,87 @@ And that's it! With this relatively small amount of code, we now have access to

## Association Methods

Go ahead and run the test suite and you'll see that we are passing the first 14 tests! Amazing! Our associations are all working, just because of our migrations and use of macros.
Go ahead and run the test suite and you'll see that we are passing the first 14 tests. Our associations are all working, just because of our migrations and use of macros.

Let's play around with our code.
We can now call methods on the objects we associated with one another. Let's play around with our code.

In your console, run `rake console`. Now we are in a Pry console that accesses our models.

Let's make a few new songs:

```bash
[1]pry(main)> hello = Song.create(name: "Hello")
```ruby
hello = Song.create(name: "Hello")
=> #<Song:0x007fc75a8de3d8 id: nil, name: "Hello", artist_id: nil, genre_id: nil>
[2]pry(main)> hotline_bling = Song.create(name: "Hotline Bling")
=> #<Song:0x007fc75b9f3a38 id: nil, name: "Hotline Bling", artist_id: nil, genre_id: nil>
```

Okay, here we have two songs. Let's make some artists to associate them to. In the *same PRY sessions as above*:

```bash
[3] pry(main)> adele = Artist.create(name: "Adele")
adele = Artist.create(name: "Adele")
=> #<Artist:0x007fc75b8d9490 id: nil, name: "Adele">
[4] pry(main)> drake = Artist.create(name: "Drake")
=> #<Artist:0x007fc75b163c60 id: nil, name: "Drake">
```

So, we know that an individual song has an `artist_id` attribute. We *could* associate `hello` to `adele` by setting `hello.artist_id=` equal to the `id` of the `adele` object. BUT! Active Record makes it so easy for us. The macros we implemented in our classes allow us to associate a song object directly to an artist object:

```bash
[5] pry(main)> hello.artist = adele
hello.artist = adele
=> #<Artist:0x007fc75b8d9490 id: nil, name: "Adele">
```

Now, we can ask `hello` who its artist is:

```bash
[6] pry(main)> hello.artist
hello.artist
=> #<Artist:0x007fc75b8d9490 id: nil, name: "Adele">
```

We can even chain methods to ask `hello` for the *name* of its artist:

```bash
[7] pry(main)> hello.artist.name
hello.artist.name
=> "Adele"
```

Wow!

Go ahead and do the same for `hotline_bling` and `drake`.

We can also ask our artists what songs they have. Let's make a second song for adele first:

```bash
[8] pry(main)> someone_like_you = Song.create(name: "Someone Like You")
=> #<Song:0x007fc75b5cabc8 id: nil, name: "Someone Like You", artist_id: nil, genre_id: nil>
[8] pry(main)> someone_like_you.artist = adele
=> #<Artist:0x007fc75b8d9490 id: nil, name: "Adele">
```

Now let's ask `adele` for her songs:
We can tell the artist about their song:

```bash
[9] pry(main)> adele.songs
=> []
```

Huh? How can `adele`'s collection of songs be empty? We associated two songs with `adele`! Here's the thing, and this is important to remember:

**The model that `has_many` is considered the parent. The model that `belongs_to` is considered the child. If you tell the child that it belongs to the parent, *the parent won't know about that relationship*. If you tell the parent that a certain child object has been added to its collection, *both the parent and the child will know about the association*.**

Let's see this in action. Let's create another new song and add it to `adele`'s songs collection:

```bash
[10] pry(main)> rolling_in_the_deep = Song.create(name: "Rolling in the Deep")
rolling_in_the_deep = Song.create(name: "Rolling in the Deep")
=> #<Song:0x007fc75bb4d1e0 id: nil, name: "Rolling in the Deep", artist_id: nil, genre_id: nil>
```

```bash
[11] pry(main)> adele.songs << rolling_in_the_deep
adele.songs << rolling_in_the_deep
=> [ #<Song:0x007fc75bb4d1e0 id: nil, name: "Rolling in the Deep", artist_id: nil, genre_id: nil>]
[12] pry(main)> rolling_in_the_deep.artist
rolling_in_the_deep.artist
=> #<Artist:0x007fc75b8d9490 id: nil, name: "Adele">
```
We added `rolling_in_the_deep` to `adele`'s collection of songs and we can see the `adele` knows it has that song in the collection *and* `rolling_in_the_deep` knows about its artist.
Notice that `adele.songs` returns an array of songs. When a model `has_many` of something, it will store those objects in an array. To add to that collection, we use the shovel operator, `<<`, to operate on that collection, treat `adele.songs` like any other array.
# Let's get started with the lab
Be sure to run `rake db:migrate`
Let's play around with some genres and our has many through association.
We are going to write some methods of our own. We want to take advantage of our new methods, thanks to the ActiveRecord macros. Therefore, every method we write will use some code that was generated by a macro. For example:
```bash
[13] pry(main)> pop = Genre.create(name: "pop")
=> #<Genre:0x007fa34338d270 id: 1, name: "pop">
```ruby
class Artist
def get_first_song
end
end
```
```bash
[14] pry(main)> pop.songs << rolling_in_the_deep
=> [#<Song:0x007fc75bb4d1e0 id: nil, name: "Rolling in the Deep", artist_id: nil, genre_id: nil>]
[15] pry(main)> pop.songs
=> [#<Song:0x007fc75bb4d1e0 id: nil, name: "Rolling in the Deep", artist_id: nil, genre_id: nil>]
[16] pry(main)> rolling_in_the_deep.genre
=> #<Genre:0x007fa34338d270 id: 1, name: "pop">
[17] pry(main)> pop.artists
=> [#<Artist:0x007fa342e34dc8 id: 1, name: "Adele">]
How would you write the `#get_first_song` method so that it returns the first `song` object saved to the artist it's called on? By using the macros! Just like above when we called `adele.songs`, we now want to call `songs` on the instance that the method will be called on in the future. How do we do that? Yes, `self`!
```ruby
class Artist
def get_first_song
self.songs
end
end
```
It's working!
This will return an array of the artist's songs. Since our method is specifically looking for the first song, we just have to chain on a `first`.
```ruby
class Artist
def get_first_song
self.songs.first
end
end
```
We'll do a handful of methods like this one for the `Song`, `Artist`, and `Genre` classes. This lab is test driven, so you can follow the specs.

0 comments on commit 5c32203

Please sign in to comment.