Hi Marty, Looking at your code, I notice first off that you've got some unnecessary lines. attr_reader attr_writer attr_accessor You don't need all 3 of these. Let's take a quick look at what this does. class Student attr_reader :name def initialize(name) @name = name end end attr_reader in the above case, will add the attribute 'name' to the class, ever instance of the Student class will have an attribute named 'name' attached to it. It also creates a method on the Student class that will return the value of the name attribute. The name attribute is stored inside of a special variable called an 'instance' variable. An instance variable is a variable in Ruby beginning with an @ and it's available in scope to the entire instance of the class. So, if we continue the above code with... student_one = Student.new("Marty Carr") # => # puts student_one.name # >> Marty Carr However, right now if you were to try... student_one.name = "Bob Bobertson" # ~> -:13:in `
': undefined method `name=' for # (NoMethodError) Why's this? It's because the attr_reader helper doesn't define a method for setting the instance variable, it only defines a method for accessing it. Let's alter the above sample code a tiny bit, and make it an attr_writer instead. class Student attr_writer :name def initialize(name) @name = name end end student_one = Student.new("Marty Carr") # => # student_one.name = "Bob Bobertson" # => "Bob Bobertson" puts student_one.name # ~> -:12:in `
': undefined method `name' for # (NoMethodError) See what happened this time? You've now got a method for name= which will set @name on the class, but, no method for reading the attribute back out. You could add this manually by defining... class Student attr_writer :name def initialize(name) @name = name end def name @name end end student_one = Student.new("Marty Carr") # => # student_one.name = "Bob Bobertson" # => "Bob Bobertson" puts student_one.name # >> Bob Bobertson So, lastly, there's a helper for if you need/want/desire both functionalities, and that's the attr_accessor helper. class Student attr_accessor :name def initialize(name) @name = name end end student_one = Student.new("Marty Carr") # => # student_one.name = "Bob Bobertson" # => "Bob Bobertson" puts student_one.name # >> Bob Bobertson See how that works? Now, one of the examples you gave was calculating an average score across multiple students. So, to keep things simple, let's take our above code, and give an instance of Student a score. class Student attr_accessor :name, :score def initialize(name, score) @name = name @score = score end end students = [] students << Student.new("Marty Carr", 100) # => [#] students << Student.new("Bob Bobertson", 77) # => [#, #] students << Student.new("George Carlson", 83) # => [#, #, #] At this point, we've got three students, and we want an average of their scores. We can do... class Student attr_accessor :name, :score def initialize(name, score) @name = name @score = score end end students = [] students << Student.new("Marty Carr", 100) # => [#] students << Student.new("Bob Bobertson", 77) # => [#, #] students << Student.new("George Carlson", 83) # => [#, #, #] number_of_students = students.count # => 3 students.map { |student| student.score }.reduce(0) { |sum, x| sum + x / number_of_students.to_f } # => 86.66666666666667 To get a better picture of the above, I'll break it apart. scores = students.map { |student| student.score } # => [100, 77, 83] total = scores.reduce(0) { |sum, x| sum + x } # => 260 total / number_of_students # => 86 total / number_of_students.to_f # => 86.66666666666667 Pretty cool, huh? Let's say you wanted to do multiple classrooms now. You probably wouldn't make the students responsible for tracking the classroom, we might have something else for that. class Classroom attr_accessor :students, :name def initialize(name) @students = [] @name = name end def add_student(student) @students << student end def average @students.map { |student| student.score }.reduce(0) { |sum, x| sum + x / @students.count.to_f } end end class Student attr_accessor :name, :score def initialize(name, score) @name = name @score = score end end a = Student.new("Marty Carr", 100) # => # b = Student.new("Bob Bobertson", 77) # => # c = Student.new("George Carlson", 83) # => # room_one = Classroom.new "Science" room_one.add_student(a) # => [#] room_one.add_student(b) # => [#, #] room_one.add_student(c) # => [#, #, #] room_one.average # => 86.66666666666667 room_two = Classroom.new "Math" room_two.add_student(Student.new("William Shatner", 55)) # => [#] room_two.add_student(Student.new("Leonard Nimoy", 97)) # => [#, #] room_two.average # => 76.0