# ActiveRecord Associations Lab

## Objectives

* Understand the common methods we have access to from our Active Record associations
* Use the methods that Active Record gives you based on your associations

Previously, we learned what Active Record associations are and how to use them. In this lab, we are going to start with the association relationships already coded for `Songs`, `Genres`, and `Artists`. These associations look like this:

* Artists have many songs and a song belongs to an artist.
* Artists have many genres through songs.
* Songs belong to a genre.
* A genre has many songs.
* A genre has many artists through songs.

You may recall that by writing a few migrations and making use of the appropriate Active Record macros, we will be able to:

* ask an Artist about its songs and genres
* ask a Song about its genre and its artist
* ask a Genre about its songs and artists.

We will build these associations through the use of Active Record migrations and macros.

### Building our Migrations

You can take a look at the migration, if you need a reminder of the tables' structures. Run `rake db:migrate` in your terminal to execute our table creations.

### Building our Associations using AR Macros

We used the following AR macros (or methods): [`has_many`](http://guides.rubyonrails.org/association_basics.html#the-has-many-association), [`has_many through`](http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association), [`belongs_to`](http://guides.rubyonrails.org/association_basics.html#the-belongs-to-association). They helped us associate `songs`, `genres`, and `artists`.

```
class Song < Active Record::Base
  belongs_to :artist
  belongs_to :genre
end
```

```
class Artist < Active Record::Base
  has_many :songs
  has_many :genres, through: :songs
end
```

```
class Genre < Active Record::Base
  has_many :songs
  has_many :artists, through: :songs
end
```

And that's it! With this relatively small amount of code, we now have access to a whole host of methods provided by Active Record.

## Association Methods

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.

We can now call methods on the objects we associated with one another. Let's play around with our code using the console task we wrote for you in the Rakefile.

```
hello = Song.create(name: "Hello")
=> #<Song:0x007fc75a8de3d8 id: 1, name: "Hello", artist_id: nil, genre_id: nil>
```

```
adele = Artist.create(name: "Adele")
=> #<Artist:0x007fc75b8d9490 id: 1, name: "Adele">
```

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:

```
hello.artist = adele
=> #<Artist:0x007fc75b8d9490 id: 1, name: "Adele">
```

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

```
hello.artist
=> #<Artist:0x007fc75b8d9490 id: 1, name: "Adele">
```

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

```
hello.artist.name
=> "Adele"
```

We can tell the artist about their song:

```
rolling_in_the_deep = Song.create(name: "Rolling in the Deep")
=> #<Song:0x007fc75bb4d1e0 id: 2, name: "Rolling in the Deep", artist_id: nil, genre_id: nil>
```

```
adele.songs << rolling_in_the_deep
=> #[ <Song:0x007fc75bb4d1e0 id: 2, name: "Rolling in the Deep", artist_id: 1, genre_id: nil> ]

rolling_in_the_deep.artist
=> #<Artist:0x007fc75b8d9490 id: 1, name: "Adele">
```

## Starting the Lab

Be sure to run `rake db:migrate`

We are going to write some methods of our own. We want to take advantage of our new methods, thanks to the Active Record macros. Therefore, every method we write will use some code that was generated by a macro. For example:

```
class Artist
  def get_first_song

  end
end
```

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

```
class Artist
  def get_first_song
    self.songs
  end
end
```

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

```
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 follow the specs and read the test error messages for additional information.

The below methods are defined in the `artist.rb`, `genre.rb` and `song.rb` within `app/models`, but are all currently empty. Write implementations for each using ActiveRecord methods.

### Artist Methods

#### `#get_genre_of_first_song`

Returns the genre of the artist's first saved song (maybe the `#get_first_song` method can be used here?)

#### `#song_count`

Return the total number of songs associated with the artist

#### `#genre_count`

Return the total number of genres associated with the artist

### Genre Methods

#### `#song_count`

Return the total number of songs associated with the genre

#### `#artist_count`

Return the number of artists associated with the genre

#### `#all_artist_names`

Return an array of strings containing every musician's name

### Song Methods

#### `#get_genre_name`

Return the name of the genre this song belongs to

#### `#drake_made_this`

For the final method in this lab, rather than return a specific value or set of values like the previous labs, your task is to create an association between a song and an artist. In this case, we'll use one artist for simplicity - Drake.

When this method is called, it should assign the song's artist to Drake. Drake doesn't exist in the database as an artist yet, so you'll have to create a record. However, if this method is run multiple times, you won't want to create a new record *each time*. Rather, you only want to create a record if Drake is not found in the database already. Once found or created, assign this song to the drake Artist instance.

<https://github.com/learn-co-curriculum/Active-Record-Association-Methods>
