Created
December 17, 2015 23:48
-
-
Save pinkopaque22/52a965f5c5cdd88f06f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__Details__ | |
As you know from completing the previous exercise, it is tedious to write numerous getter and setter methods. Getter and setter methods are so common that Ruby provides a shortcut to create them. The attr_accessor method creates a getter and setter method based on an argument. You pass attr_accessor a Symbol: | |
class Square | |
attr_accessor :size | |
end | |
s = Square.new | |
s.size = 10 # This is the setter | |
s.size #=> 10 # This is the getter | |
We now have getter and setter methods for size, because we called: | |
attr_accessor :size | |
The size=() and size methods are dynamically generated when we add attr_accessor :size to Square. | |
Behold the magic of Ruby! It's actually not magic but "dynamic programming", which we'll cover later. | |
To complete this exercise, create a Playlist class. It should have attributes for name, author, and song_list. These attributes should be readable and writable. | |
__Specs__ | |
describe "Playlist" do | |
describe "instance variables" do | |
it "should be able to create a country playlist" do | |
playlist = Playlist.new | |
# Setters | |
playlist.name = "Country" | |
playlist.author = "Blake Shelton" | |
playlist.song_list = ["Sure Be Cool If You Did", "God Gave Me You"] | |
# Getters | |
expect( playlist.name ).to eq("Country") | |
expect( playlist.author ).to eq("Blake Shelton") | |
expect( playlist.song_list ).to eq(["Sure Be Cool If You Did", "God Gave Me You"]) | |
end | |
it "should be able to create a Rock playlist" do | |
playlist = Playlist.new | |
# Setters | |
playlist.name = "Rock" | |
playlist.author = "R&R" | |
playlist.song_list = ["Radioactive", "Clouds"] | |
# Getters | |
expect( playlist.name ).to eq("Rock") | |
expect( playlist.author ).to eq("R&R") | |
expect( playlist.song_list ).to eq(["Radioactive", "Clouds"]) | |
end | |
end | |
end | |
__Code__ | |
class Playlist | |
attr_accessor :name | |
n = Playlist.new | |
n.name | |
attr_accessor :author | |
a = Playlist.new | |
a.author | |
attr_accessor :song_list | |
s = Playlist.new | |
s.song_list | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__Details__ | |
Create a Book class with three instance methods: | |
set_title(title) should take an argument and use it to set the @title instance variable. | |
set_author(author) should take an argument and use it to set the @author instance variable. | |
Finally, description should accept no arguments and return a string formatted as: "Title was written by author" using the @title and @author instance variables. | |
__Specs__ | |
describe "Book" do | |
describe "setters" do | |
it "should respond to #set_title" do | |
expect(Book.new).to respond_to(:set_title) | |
end | |
it "should set @title" do | |
book = Book.new | |
book.set_title("Z for Zachariah") | |
expect(book.instance_variable_get(:@title)).to eq("Z for Zachariah") | |
end | |
it "should respond to #set_author" do | |
expect(Book.new).to respond_to(:set_author) | |
end | |
it "should set @author" do | |
book = Book.new | |
book.set_author("Robert C. O'Brien") | |
expect(book.instance_variable_get(:@author)).to eq("Robert C. O'Brien") | |
end | |
end | |
describe "#description" do | |
it "should return the correct title and author" do | |
book = Book.new | |
book.set_title("Railsea") | |
book.set_author("China Miéville") | |
expect(book.description).to eq("Railsea was written by China Miéville") | |
end | |
it "should return the correct title and author" do | |
book = Book.new | |
book.set_title("The Tombs of Atuan") | |
book.set_author("Ursula Le Guin") | |
expect(book.description).to eq("The Tombs of Atuan was written by Ursula Le Guin") | |
end | |
end | |
end | |
__Code__ | |
class Book | |
def set_title(title) | |
@title = title | |
end | |
def set_author(author) | |
@author = author | |
end | |
def description | |
"#{@title} was written by #{@author}" | |
end | |
end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__Details__ | |
As we learned in the checkpoint, getter and setter methods can access attributes of a class instance. | |
Let's explore another example as a refresher. Below we define two methods in the Car class. The color=(c) method sets the @color instance variable, and the color method gets the @color instance variable. The last two lines of code below demonstrate how the getter and setter methods are used on the ferrari instance of the Car class: | |
class Car | |
def color=(c) | |
@color = c | |
end | |
def color | |
@color | |
end | |
end | |
ferrari = Car.new | |
ferrari.color = "Red" # setter | |
ferrari.color # getter | |
#=> "Red" | |
The = in color=(c) makes the setter method more idiomatic. The Ruby interpreter lets you put a space between the equal sign and the method. The following two lines are equivalent. | |
ferrari.color=("Red") | |
ferrari.color = "Red" | |
Most Rubyists prefer the latter syntax with the extra spaces. | |
To complete this exercise, rewrite your Book class from the previous exercise. The new Book class should have attributes to describe its title, number of pages, and author. | |
These instance variables should be settable and gettable. | |
__Specs__ | |
describe "Book" do | |
describe "should be able get/set attributes for Wool" do | |
it "should be able to get/set title" do | |
b = Book.new | |
b.title = "A Slight Trick of the Mind" | |
expect(b.title).to eq("A Slight Trick of the Mind") | |
end | |
it "should be able to get/set pages" do | |
b = Book.new | |
b.pages = 528 | |
expect(b.pages).to eq(528) | |
end | |
it "should be able to get/set author" do | |
b = Book.new | |
b.author = "Hugh Howey" | |
expect(b.author).to eq("Hugh Howey") | |
end | |
end | |
describe "should be able get/set attributes for Station Eleven" do | |
it "should be able to get/set title" do | |
b = Book.new | |
b.title = "Station Eleven" | |
expect(b.title).to eq("Station Eleven") | |
end | |
it "should be able to get/set pages" do | |
b = Book.new | |
b.pages = 352 | |
expect(b.pages).to eq(352) | |
end | |
it "should be able to get/set author" do | |
b = Book.new | |
b.author = "Emily St. John Mandel" | |
expect(b.author).to eq("Emily St. John Mandel") | |
end | |
end | |
end | |
__Code__ | |
class Book | |
def title=(t) | |
@title = t | |
end | |
def title | |
@title | |
end | |
def pages=(pg) | |
@pages = pg | |
end | |
def pages | |
@pages | |
end | |
def author=(a) | |
@author = a | |
end | |
def author | |
@author | |
end | |
end | |
book = Book.new | |
book.title = "@title" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__Details__ | |
The RSpec which tests your code can fail or pass, but it can also raise errors. If the RSpec errors, nothing in the console will run. | |
To test this, try some basic functionality in the console: | |
p "The console is not erroring." | |
If you hit run, you may be dismayed that the console is erroring, and your code doesn't print. This is because the specs testing this code expect certain things in the code that aren't there. If your code doesn't behave as expected, the specs will fail. On the other hand, if your code doesn't have certain expected components, the specs won't even arrive at failure, and they'll bring the console down with them. | |
Let's review the error message. The important part is: | |
uninitialized constant MadeUpClass | |
This error is telling us the spec is looking for a "constant" (think "class") named MadeUpClass, and because the spec isn't finding this constant, the spec is throwing an error. We can solve this error by defining the MadeUpClass class in our console: | |
class MadeUpClass | |
end | |
If you run the code again, you'll get a NoMethodError saying undefined method 'return_string' for #<MadeUpClass:0x007f0c32dbb600> (or some other number). This is a similar failure, but now it's a failure, not an interpreter error. You can see this by trying to print something again. Although the tests are failing, your output should be printed below them. | |
This test failure tells us the spec expects the return_string method to be defined on instances of MadeUpClass. To fix this, let's add that method: | |
class MadeUpClass | |
def return_string | |
end | |
end | |
Press run again. We get RSpec::Expectations::ExpectationNotMetError, with a message telling us that the test expected a specific string to be returned from the method, while the method returned nothing (nil). | |
To make the tests pass, return that string from the method. | |
This exercise should familiarize you with some errors you might encounter in this console, and how to deal with them. | |
Look out for these errors if you try to run example code in the in-browser Ruby console (which runs specs which can have class expectations). They might prohibit your code from running, so if you want to test out basic Ruby, we suggest using irb. | |
Error messages in Ruby are generally quite helpful. Always read them and consider their meaning. | |
__Specs__ | |
describe MadeUpClass do | |
describe "#return_string" do | |
it "returns the right string" do | |
expect( MadeUpClass.new.return_string ).to eq("String to return") | |
end | |
end | |
end | |
__Code__ | |
class MadeUpClass | |
def return_string | |
p "String to return" | |
end | |
end | |
__Results__ | |
"String to return" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment