Reputation: 1
I'm working through the learn ruby tutorials and I'm trying pass the last example where it tests the printable method. I tested the method by calling the method directly within my ruby program and it spits out exactly whats needed. What is preventing my code from properly passing? Any help is greatly appreciated.
Here's the rspec file:
require 'dictionary'
describe Dictionary do
before do
@d = Dictionary.new
end
it 'is empty when created' do
@d.entries.should == {}
end
it 'can add whole entries with keyword and definition' do
@d.add('fish' => 'aquatic animal')
@d.entries.should == {'fish' => 'aquatic animal'}
@d.keywords.should == ['fish']
end
it 'add keywords (without definition)' do
@d.add('fish')
@d.entries.should == {'fish' => nil}
@d.keywords.should == ['fish']
end
it 'can check whether a given keyword exists' do
@d.include?('fish').should be_false
end
it "doesn't cheat when checking whether a given keyword exists" do
@d.include?('fish').should be_false # if the method is empty, this test passes with nil returned
@d.add('fish')
@d.include?('fish').should be_true # confirms that it actually checks
@d.include?('bird').should be_false # confirms not always returning true after add
end
it "doesn't include a prefix that wasn't added as a word in and of itself" do
@d.add('fish')
@d.include?('fi').should be_false
end
it "doesn't find a word in empty dictionary" do
@d.find('fi').should be_empty # {}
end
it 'finds nothing if the prefix matches nothing' do
@d.add('fiend')
@d.add('great')
@d.find('nothing').should be_empty
end
it "finds an entry" do
@d.add('fish' => 'aquatic animal')
@d.find('fish').should == {'fish' => 'aquatic animal'}
end
it 'finds multiple matches from a prefix and returns the entire entry (keyword + definition)' do
@d.add('fish' => 'aquatic animal')
@d.add('fiend' => 'wicked person')
@d.add('great' => 'remarkable')
@d.find('fi').should == {'fish' => 'aquatic animal', 'fiend' => 'wicked person'}
end
it 'lists keywords alphabetically' do
@d.add('zebra' => 'African land animal with stripes')
@d.add('fish' => 'aquatic animal')
@d.add('apple' => 'fruit')
@d.keywords.should == %w(apple fish zebra)
end
it 'can produce printable output like so: [keyword] "definition"' do
@d.add('zebra' => 'African land animal with stripes')
@d.add('fish' => 'aquatic animal')
@d.add('apple' => 'fruit')
@d.printable.should == %Q{[apple] "fruit"\n[fish] "aquatic animal"\n[zebra] "African land animal with stripes"}
end
end
and here's what I've created so far for the printable function:
class Dictionary
def initialize(opts = {})
@opts = opts
end
def entries
@opts
end
def add(opts)
opts.is_a?(String) ? @opts.merge!(opts => nil) : @opts.merge!(opts)
end
def keywords
@opts.keys.sort
end
def include?(key)
@opts.has_key?(key)
end
def find(key)
@opts.select { |word,defin| word.scan(key).join == key }
end
def printable
opts_sorted = @opts.sort_by { |word,defin| word}
opts_sorted.each do |word,defin|
print "[#{word}] \"#{defin}\"\n"
end
end
end
and here's the error:
1) Dictionary can produce printable output like so: [keyword] "definition"
Failure/Error: @d.printable.should == %Q{[apple] "fruit"\n[fish] "aquatic animal
"\n[zebra] "African land animal with stripes"}
expected: "[apple] \"fruit\"\n[fish] \"aquatic animal\"\n[zebra] \"African lan
d animal with stripes\""
got: [["apple", "fruit"], ["fish", "aquatic animal"], ["zebra", "African
land animal with stripes"]] (using ==)
Diff:
@@ -1,4 +1,4 @@
-[apple] "fruit"
-[fish] "aquatic animal"
-[zebra] "African land animal with stripes"
+["apple", "fruit"]
+["fish", "aquatic animal"]
+["zebra", "African land animal with stripes"]
# ./11_dictionary/dictionary_spec.rb:81:in `block (2 levels) in <top (required)>
'
Upvotes: 0
Views: 1069
Reputation:
Lucky for you I did this whole thing just now! Below is the answer code with comments for the explanation! I hope this still helps even after 4 years!
class Dictionary # Create the class
attr_accessor :entries # Attribute Accessor; this is our setter and getter
def initialize(entries = {}) # Create constructor; if there is no value passed the default value is {}
@entries = {} # Declare instance variable with empty hash
if entries.is_a? Hash # is_a? is a method where it sees if its a class; Hash is the class we compare it to
entries.each {|key, value| @entries[key] = value} # if there is a value that's passed we copy the hash to our instance variable
end # End conditional
end # End constructor
def keywords # Main purpose of this method is to return what's inside our keys
keywords = [] # Create empty keyword variable
@entries.each_key {|key| keywords.push(key.to_s)} # each_key method only takes the keys in our hash and pushes them into the keywords array
keywords.sort # We sort the keywords variable
end # End method
def add(entry) # add method adds in an entry either a hash or a string
if entry.is_a? Hash # If the argument belongs to the class Hash; or if its a hash
entry.each {|key, value| @entries[key] = value} # Then we copy the key and values to our instance variable
elsif entry.is_a? String # If the arguemnt belongs to the class String; or if its a String
@entries[entry] = nil # We create a key for that string and set the value to nil
end # End conditional
end # End method
def include?(entry) # include? method this checks if the argument is in our entries and returns a boolean value
@entries.has_key?(entry) # has_key? checks the instance variable if it has the key
end # End method
def find(entry) # find method finds if certain letters are in our keys
@entries.select {|key| /#{entry}/.match(key)} # select gets the keys that match a certain keyword in our entries
# if @entries.has_key?(entry) # First attepmt to solve the test case
# @entries.select {|key,value| key == entry}
# else
# puts {}
# end
end # End method
def printable # printable method just prints out our entries like a dictionary
printable = [] # Create an empty array
@entries.sort.each do |key,value| # Sort and iterate to each key-value pair
printable.push("[#{key}] \"#{value}\"") # push the key-value pair formatted accordingly to the test case
end # End hash iteration
printable.join("\n") # join with newlines to get desired result
end # End method
end # End class
Upvotes: 1
Reputation: 15736
I think the problem is that your printable
method is not returning what you want it to return.
The return value of printable
is the value of the method's last statement (opts_sorted.each ...
). You are using print
to output the expected string but this does not change the return value of the method (which is what you are testing).
If you want to return the string you are printing instead try this:
def printable
opts_sorted = @opts.sort_by { |word, defin| word}
opts_sorted.map{ |word, defin| "[#{word}] \"#{defin}\"\n" }.join
end
map
will transform the key-value pairs in the hash into an array of strings formatted the way you want them and then join
will append them into a single string.
Upvotes: 0