0

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)>
'
4

2 回答 2

1

幸运的是,我刚刚完成了这一切!以下是带有注释的答案代码以供解释!我希望即使在 4 年后这仍然有帮助!

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
于 2017-12-12T08:23:51.413 回答
0

我认为问题在于您的printable方法没有返回您希望它返回的内容。

的返回值printable是方法的最后一条语句 ( opts_sorted.each ...) 的值。您正在使用print输出预期的字符串,但这不会更改方法的返回值(这是您正在测试的)。

如果您想返回正在打印的字符串,请尝试以下操作:

def printable
  opts_sorted = @opts.sort_by { |word, defin| word}
  opts_sorted.map{ |word, defin| "[#{word}] \"#{defin}\"\n" }.join
end

map将散列中的键值对转换为按您希望的方式格式化的字符串数组,然后join将它们附加到单个字符串中。

于 2013-08-23T08:14:22.437 回答