如何创建一个将哈希(带或不带指定值)作为参数的方法?

时间:2015-04-11 07:36:04

标签: ruby rspec

所以我首先通过测试并且有点卡住了。到目前为止,这是我的代码:

class Dictionary 
  attr_accessor :entries, :keywords, :item

  def initialize 
    @entries = {}
end

  def add(item)
    item.each do |words, definition| 
      @entries[words] = definition
    end
  end

  def keywords
    @entries.keys
  end

end#class

我在这里停留在rspec测试中:

it 'add keywords (without definition)' do
    @d.add('fish')
    @d.entries.should == {'fish' => nil}
    @d.keywords.should == ['fish']
  end

如何切换我的add方法以获取键/值对,或只是将值设置为nil的键?第一个测试指定哈希在创建时是空的,所以我不能在那里给它默认值。

2 个答案:

答案 0 :(得分:3)

可以检查传递给add方法的参数的类型。不管它是Enumerable,显然是Array s,Hash es等中包含的mixin,只需将其值分配给nil

def add(item)
  case item
  when Enumerable
    item.each do |words, definition| 
      @entries[words] = definition
    end
  else
    @entries[item] = nil
  end
end

请注意case使用“case equality”来检查参数类型。

答案 1 :(得分:2)

如果你总是将Strings传递给方法,你可能只有第二个字符串的默认值......如下所示:

  def add(word, definition = nil)
      @entries[word] = definition
  end

所以你的代码看起来像这样:

class Dictionary 
  attr_accessor :entries, :keywords, :item

  def initialize 
    @entries = {}
  end

  def add(word, definition = nil)
      @entries[word] = definition
  end

  def keywords
    @entries.keys
  end

end#class

如果您想要多次添加(即add key: "word", with: "many", options: nil),那么该设计可能对您不起作用,您需要创建一个可以在@mudasobwa建议的方面工作的解决方案。也许:

  def add(word, definition = nil)
      return @entries[word] = definition unless word.is_a?(Enumerable)
      return @entries.update word if word.is_a?(Hash)
      raise "What?!"
  end

以par请求更新

我更新了上面的方法以允许不是字符串的单词(正如您所指出的那样)。

将哈希传递给方法时,它被视为单个参数。

Key =>值对是隐含的哈希,因此在将哈希传递给方法时,以下内容通常是相同的:

Hash.new.update key: :value
Hash.new.update({key: :value})

请考虑以下事项:

def test(a,b = nil)
  puts "a = #{a}"
  puts "b = #{b}"
end

test "string"
# => a = string
# => b = 
test "string", key: :value, key2: :value2
# => a = string
# => b = {:key=>:value, :key2=>:value2}
test key: :value, key2: :value2, "string"
# Wrong Ruby Syntax due to implied Hash, would raise exception:
# => SyntaxError: (irb):8: syntax error, unexpected '\n', expecting =>
test({key: :value, key2: :value2}, "string")
# correct syntax.

这就是为什么当你通过add 'fish' => 'aquatic'时,它只被认为是一个参数,一个哈希 - 而不是add 'fish', 'aquatic',它将两个参数传递给方法。

如果您的方法必须接受不同类型的参数(字符串,散列,数字,符号,数组),您将需要以不同的方式处理每个选项。

这就是为什么@mudasobwa建议检查第一个参数的类型。他的解决方案相当不错。

我的版本对代码来说有点短,但它的运行方式相同。

  def add(word, definition = nil)
      return @entries[word] = definition unless word.is_a?(Enumerable)
      return @entries.update word if word.is_a?(Hash)
      raise "What?!"
  end