2015-01-03 4 views
1

Я новичок в рубине и просматриваю учебник, посвященный блокам и урокам, и особенно демонстрирую Monkey Patching.Блоки и выходы по устранению неполадок в рубине

Вот требование кода вызова

Написать новый метод new_map, который вызывается на экземпляре класса Array. Он должен использовать> массив, который он вызывается как неявный (сам) аргумент, но в противном случае ведет себя одинаково.

Вот код, который я представил

class Array 

    def new_map(&block) 
    self.map(&block) 
    end 

    def new_select!(&block) 
    self.replace(self.select(&block)) 
    end 

end 

Вот функции я должен пройти

describe Array do 
    describe '#new_map' do 
    it "returns an array with updated values" do 
    array = [1,2,3,4] 
    expect(array.new_map(&:to_s)).to eq(%w{1 2 3 4}) 
    expect(array.new_map{ |e| e + 2 }).to eq([3, 4, 5, 6]) 
    end 

    it "does not call #map" do 
    array = [1,2,3,4] 
    array.stub(:map) { '' } 
    expect(array.new_map(&:to_s)).to eq(%w{1 2 3 4}) 
    end 

    it "does not change the original array" do 
     array = [1,2,3,4] 
     expect(array.new_map(&:to_s)).to eq(%w{1 2 3 4}) 
     expect(array).to eq([1,2,3,4]) 
    end 
end 

Я прошел первый и последний тест, но не смог пройти второй и получена эта ошибка

expected: ["1", "2", "3", "4"] 
    got: "" 

(compared using ==) 

exercise_spec.rb:14:in `block (3 levels) in <top (required)>' 

Из спецификации, a m I предположить, что метод .map не должен использоваться в этой конкретной проблеме?

Я даже попробовал это с этим допущением. Но он не прошел ни одного из спецификаций.

def new_map(array) 
    new_array =[] 
    array.each do |i| 
    new_array << yield(i) 
    end 
    new_array 
end 

Update

Я вошел в этот код и он работал

def new_map 
    new_array = [] 
    self.each do |i| 
    new_array << yield(i) 
    end 
    new_array 
end 

Но я надеялся, что кто-то может помочь мне понять, почему я должен был удалить аргумент (array) и, следовательно, изменить array.each к self.each?

ответ

0

Но я надеялся, что кто-то может помочь мне понять, почему я должен был удалить аргумент (массив) и, следовательно, изменить array.each к self.each?

  1. фон: Ваш первый метод ищет аргумент, который на самом деле не нужно быть передан как массив является сам абонент; другими словами, вы пытаетесь передать вызывающего абонента (или self) в качестве аргумента для метода. Технически вы можете это сделать, но это не требуется.
  2. Причина отказа: Но если у вас возникла ошибка при запуске спецификаций с предыдущим определением, потому что определение метода было изменено путем добавления этого аргумента. То есть, вы должны вызова метода 1, как это:

    new_map массив {блок}

Хотя массив аргументов фактически не передается, следовательно, давая вам ArgumentError.

+0

Пожалуйста, обратите внимание на правильность маркировки, если она решила вашу проблему. –

0

new_map является метод экземпляра класса массива делает ваш массив == само

[1,2,3].new_map(&:to_s) 

само является [1,2,3], что ваш экземпляр массива

self.each do |i| 

это, как

[1,2,3].each do |i| 

тогда каждый из 1,2 и 3 будут переданы в блок

new_array << yield(i) 
+0

Спасибо, по сути, поскольку метод new_map является экземпляром класса Array, передавая аргумент как (массив), становится излишним? – deventhusiast

+0

да действительно. И просматривая спецификации, которые вам нужно передать, вам нужно только передать блок. –