Code Monkey home page Code Monkey logo

ruby-objects-has-many-through-lab's Introduction

Ruby Object Relations: Has-Many-Through Lab

Objectives

  • Write classes that are related to each other via the "has-many-through" relationship.
  • Write methods that use the "has-many-through" relationship to deliver information on related objects.

Overview

In this lab, we'll be dealing with two sets of three classes.

We have a Song, Artist and Genre class. Songs belong to an artist and belong to a genre. A genre has many songs and an artist has many songs. An artist has many genres through its songs and a genre has many artists through its songs.

We also have an Appointment, Doctor and Patient class. Appointments belong to a Patient and a Doctor. A Doctor has many Appointments and a Patient has many Appointments. A Doctor has many Patients through its Appointments and a Patient has many Doctors through its Appointments.

Instructions

Start with the Artist/Song/Genre domain.

The Artist model:

  • The Artist class needs a class variable @@all that begins as an empty array
  • The Artist class needs a class method .all that lists each artist in the class variable
  • An artist is initialized with a name and is saved in the @@all array.
  • The Artist class needs an instance method, #new_song, that takes in an argument of a name and genre creates a new song. That song should know that it belongs to the artist.
  • The Artist class needs an instance method, #songs, that iterates through all songs and finds the songs that belong to that artist. Try using select to achieve this.
  • The Artist class needs an instance method, #genres that iterates over that artist's songs and collects the genre of each song.
madonna = Artist.new("Madonna")

The Genre model:

  • The Genre class needs a class variable @@all that begins as an empty array.
  • The Genre class needs a class method .all that lists each genre in the class variable.
  • A genre should be initialized with a name and be saved in the @@all array.
  • The Genre class needs an instance method, #songs, that iterates through all songs and finds the songs that belong to that genre.
  • The Genre class needs an instance method, #artists, that iterates over the genre's collection of songs and collects the artist that owns each song.
pop = Genre.new("pop")

The Song model:

  • The Song class needs a class variable @@all that begins as an empty array.
  • The Song class needs a class method .all that lists each song in the class variable.
  • A song should be initialized with a name, an artist, and a genre, and be saved in the @@all array.
madonna = Artist.new("Madonna")
pop = Genre.new("pop")

into_the_groove = Song.new("Into the Groove", madonna, pop)

Now let's move on to our Doctor/Appointment/Patient domain model.

Note: the tests will be calling your #new_appointment methods in your Doctor and Patient classes, as well as the #initialize method in the Appointment class. Therefore, in order to pass the tests, you will need to make sure that your method definitions specify the parameters in the order indicated below.

The Doctor model:

  • The Doctor class needs a class variable @@all that begins as an empty array.
  • The Doctor class needs a class method .all that lists each doctor in the class variable.
  • A doctor should be initialized with a name and be saved in the @@all array.
  • The Doctor class needs an instance method, #new_appointment, that takes in a date and an instance of the Patient class in this order, and creates a new Appointment. That Appointment should know that it belongs to the doctor
  • The Doctor class needs an instance method, #appointments, that iterates through all Appointments and finds those belonging to this doctor.
  • The Doctor class needs an instance method, #patients, that iterates over that doctor's Appointments and collects the patient that belongs to each Appointments.
doogie = Doctor.new("Doogie Howser")

The Patient model:

  • The Patient class needs a class variable @@all that begins as an empty array.
  • The Patient class needs a class method .all that lists each patient in the class variable.
  • A patient is instantiated with a name and be saved in the @@all array.
  • The Patient class needs an instance method, #new_appointment, that takes in a date and an instance of the Doctor class in this order and creates a new Appointment. The Appointment should know that it belongs to the patient.
  • The Patient class needs an instance method, #appointments, that iterates through the Appointments array and returns Appointments that belong to the patient.
  • The Patient class needs an instance method, #doctors, that iterates over that patient's Appointments and collects the doctor that belongs to each Appointment.
ferris = Patient.new("Ferris Bueller")

The Appointment model:

  • The Appointment class needs a class variable @@all that begins as an empty array.
  • The Appointment class needs a class method .all that lists each Appointment in the class variable.
  • An Appointment should be initialized with a date (as a string, like "Monday, August 1st"), a patient, and a doctor in this order. The Appointment should be saved in the @@all array.
ferris = Patient.new("Ferris Bueller")
doogie = Doctor.new("Doogie Howser")

new_appointment = Appointment.new('January 1st, 1989', ferris, doogie)

ruby-objects-has-many-through-lab's People

Contributors

annjohn avatar aviflombaum avatar danielseehausen avatar drakeltheryuujin avatar ga-be avatar geluso avatar hoffm386 avatar jmburges avatar kkterai avatar lizbur10 avatar maxwellbenton avatar morgvanny avatar pletcher avatar sgharms avatar sophiedebenedetto avatar telegraham avatar tmtarpinian avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ruby-objects-has-many-through-lab's Issues

Missing end keyword in 06_patient_spec

06_patient_spec.rb needs an end keyword to close the describe block. A syntax error is thrown if the student tries to run the test suite.

describe '#appointments' do
    it 'has many doctors through appointments' do
      doctor_dog = Doctor.new('Dog')
      doctor_howser = Doctor.new('Howser')
      steve = Patient.new('Steve from Blues Clues')
      appointment_one = steve.new_appointment(doctor_dog, 'Friday, January 32nd')
      appointment_two = steve.new_appointment(doctor_howser, 'Saturday, January 32nd')

      expect(steve.appointments).to include(appointment_one)
      expect(steve.appointments).to include(appointment_two)
    end
#add end keyword here

Doctor add appointments test message errors

Hi there, the Doctor add_appointments test is very confusing--it references adding appointments to the artists appointments array. I'd take a second look at it? Error message attached.

dr add_appointment test

Issue with patient spec file

When I ran the tests before typing anything, it kept returning an error until I added another 'end' in 06_patient_spec.rb file on line 55.

should song.artist be read-only?

Tests failed because I made my song.artist read-only. The tests construct a song passing in name, artist and genre. Then the test immediately manually assigns the same artist again.

ninety_nine_problems = Song.new("99 Problems", jay_z, rap)
ninety_nine_problems.artist = jay_z

I initially wrote my song class like this keeping each property read-only.

class Song
    attr_reader :name, :artist, :genre

    def initialize(name, artist, genre)
        @name = name
        @artist = artist
        @genre = genre
    end
end

The spec doesn't say anything about the artist being writable. Having it this way has:

Pros: forces students to look at the test error output and realize and learn what's going on.
Cons: making artist writable is non-intuitive and unspecified.

Is this inentional and should we leave it this way, or should we remove the manual assignment to artist from the test spec?

See pull request removing manual assignment for easy merge if we want to change to go that way.

Error in 06_patient_spec.rb

Need an 'end' on line 42 of master branch copy.

describe '#appointments' do
it 'has many doctors through appointments' do
doctor_dog = Doctor.new('Dog')
doctor_howser = Doctor.new('Howser')
steve = Patient.new('Steve from Blues Clues')
appointment_one = steve.new_appointment(doctor_dog, 'Friday, January 32nd')
appointment_two = steve.new_appointment(doctor_howser, 'Saturday, January 32nd')

  expect(steve.appointments).to include(appointment_one)
  expect(steve.appointments).to include(appointment_two)
end

#end here

line 47 of the doctor spec is incorrect

Unless I'm mistaken, the arguments are in the wrong order in the doctor test.

Line 47 looks like this:
doctor_who.new_appointment(hevydevy, 'Friday, January 32nd')

It should look like this:
doctor_who.new_appointment('Friday, January 32nd', hevydevy)

Bug when using binding.pry in this location

Whenever using binding.pry in the position show in the Genre class/artists method below, you end up having to exit the local IDE and losing whatever work isn't saved (to my knowledge).

require 'pry'

class Genre
  attr_accessor :name

  @@all = []

  def initialize(genre_name)
    @name = genre_name
    @@all << self
  end

  def self.all
    @@all
  end

  def songs
    Song.all.select do |song|
      song.genre == self
    end
  end

  def artists
    binding.pry
    # Song.all.select do |artist|
    #   artist.artist ==
    # end
  end



end

After iterating through the various instances you get:

screen shot 2018-10-18 at 5 54 48 am

You can't press enter or return to get back to the normal terminal.

screen shot 2018-10-18 at 5 56 13 am

screen shot 2018-10-18 at 5 56 23 am

Here is the code for the other classes that I had:

require 'pry'

class Artist
  attr_accessor :name

  @@all = []

  def initialize(name)
    @name = name
    @@all << self
  end

  def self.all
    @@all
  end

  def new_song(song_name, genre)
    Song.new(song_name, self, genre)
  end

  def songs

    Song.all.select do |song|
      song.artist == self
    end
  end

  def genres
    # binding.pry
    songs.collect do |song|
      song.genre
    end
  end


end
require 'pry'

class Song
  attr_accessor :name, :artist, :genre

  @@all = []

  def initialize(song_name, artist, genre)
    @name = song_name
    @artist = artist
    @genre = genre
    @@all << self
  end

  def self.all
    @@all
  end

  # def genre
  #   binding.pry
  # end


end

Incorrect test description

Doctor
#patients
has many patients, through patients

should be:

Doctor
#patients
has many patients, through appointments

There's a problem with the test for the #new_appointment method in the Doctor class.

Hello. Regarding the Doctor class's #new_appointment method, both the README and the #describe block in the test for #new_appointment seem to indicate that #new_appointment needs to accept its arguments in the following order: date, patient.

The only problem is, that order of arguments is supposed to be the other way around, or the test will fail. I have attached a screenshot to add some clarity.

Thanks for looking into this!

Regards,

Sdcrouse

has many objects through lab screenshot

Learn IDE

I don't know if its local to this lab or has a wider scope. But my Learn IDE in browser is refreshing itself. Getting frozen every 2 minutes. It's really hard to go through the lab this way.

OPEN IDE not working

For some reason, I cannot open the IDE at all. It is unresponsive and I am not sure why, tried on different Wifi connections to no success.

Patient-artist mixup

Sorry, another one:

"The Patient class needs a class method .all that lists each artist in the class variable.

Thank you.

Song.all

"The Song class needs a class method .all that lists each artist in the class variable."

Shouldn't this list out all the songs, and not the artists, in the class?

Appointment with an artist

Another little mixup here:

"The Appointment class needs a class method .all that lists each artist in the class variable.

Thank you.

Valerie

Doctor Class Instruction Error

"The Doctor class needs a class method .all that lists each artist in the class variable."

Small error, but this should say, "The Doctor class needs a class method .all that lists each doctor in the class variable."

Some of the tests are missing.

Hello. First of all, I understand if some of these tests may not be needed, in order to avoid redundancy.

That having been said, the README says that the Genre class needs a Genre.all method and a #new_song method. It also says that the Patient class needs a Patient.all method, a #name method, and an #appointments method. Unfortunately, there are no tests to check for this, despite other classes having similar tests for similar methods. To be fair, though, one of the tests for the Patient class does in fact require that the #appointments method be defined, in order to pass.

I know that these are minor issues, but thank you for looking into this.

Regards,

Sdcrouse

Question about the flow of this lab.

Hello there!

I was working on it through learn --f-f. The flow of this lab is asking songs method before writing it. Here's the new_song method (just before song method)

  describe "#new_song" do
    it "given a name and genre, creates a new song associated with that artist" do
      jay_z = Artist.new("Jay-Z")
      rap = Genre.new("rap")
      ninety_nine_problems = jay_z.new_song("Ninety Nine Problems", rap)

     #here jay_z.songs
      expect(jay_z.songs).to include(ninety_nine_problems)
      expect(ninety_nine_problems.artist).to eq(jay_z)
    end
  end

Shouldn't the songs method be actually before the new_song?

Does the Artist need a Doctor?

I think there is a little mixup here:

"The Doctor class needs a class method .all that lists each artist in the class variable."

Thanks,

Valerie

Error in Artist #genres test

The test for #genres under Artist expects jay_z.songs.first.genre to equal rap - the test should call jay_z.songs.last.genre, however, to access the most recent genre, which was created inside the #genres test.

Calling jay_z.songs.first.genre calls the genre created in earlier Artist tests, meaning the instances don't match up and the #genres test fails.

Remove let usage in tests

I don't think we should be using let here in the tests as it's hard to follow the narratives of the things that are suppose to occur.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.