2008-11-11 13 views
36

Próbuję wprowadzić hasło wejściowe Ruby z Highline gem, a ponieważ mam dwa razy wpisane hasło, chciałbym wyeliminować duplikację bloków, przez które przechodzę. Przykładowo, prosta wersja tego, co robię teraz to:Ruby - przekazywanie bloków do metod

new_pass = ask("Enter your new password: ") { |prompt| prompt.echo = false } 
verify_pass = ask("Enter again to verify: ") { |prompt| prompt.echo = false } 

A co chciałbym zmienić to na coś takiego:

foo = Proc.new { |prompt| prompt.echo = false } 
new_pass = ask("Enter your new password: ") foo 
verify_pass = ask("Enter again to verify: ") foo 

który niestety nie działa . Jaki jest właściwy sposób na zrobienie tego?

Odpowiedz

69

Kod przez Dawida będzie działać dobrze, ale jest to łatwiejsze i krótsze rozwiązanie:

foo = Proc.new { |prompt| prompt.echo = false } 
new_pass = ask("Enter your new password: ", &foo) 
verify_pass = ask("Enter again to verify: ", &foo) 

Można również użyć znaku handlowego przypisać blok do zmiennej przy określaniu metody:

def ask(msg, &block) 
    puts block.inspect 
end 
+0

Próbowałem tego na początku (zanim zadam to pytanie), ale kiedy to zrobię, Highline ignoruje zawartość bloku i umiera z tym błędem: niezdefiniowana metoda '& 'dla" inputstring ": String (NoMethodError) Gdzie inputstring jest tym, co wpisałem w pierwszym pytaniu. –

+0

Brzmi dziwnie. Być może zapomniałeś o przecinku i Ruby zakładała, że ​​chcesz wywołać metodę "&" w ciągu znaków zachęty? Właśnie wypróbowałem ten sam kod z HighLine i działa dobrze. –

+0

Tak, myślę, że robiłem ask ("goo") i foo zamiast pytać ("goo", i foo). To działa teraz. Dzięki Adam! –

-2

Nie sądzę, że język obsługuje taką konstrukcję. Jedynym sposobem, widzę uogólnić to w jakikolwiek sposób jest:

def foo(prompt) 
    prompt.echo = false 
end 
new_pass = ask("Enter your new password: ") { |prompt| foo(prompt) } 
verify_pass = ask("Enter again to verify: ") { |prompt| foo(prompt) } 

To naprawdę nie ma skrócić kod, choć nie usuwa pewne powielania - jeśli chcesz zrobić więcej niż ustawiony prompt.echo do false, wystarczy dodać kod w jednym miejscu.

4
foo = Proc.new { |prompt| prompt.echo = false } 
new_pass = ask("Enter your new password: ") {|x| foo.call(x)} 
verify_pass = ask("Enter again to verify: ") {|x| foo.call(x)} 
+0

To się udało! Dziękuję za szybką odpowiedź! –

13

jest to, jak należy to zrobić, czysta i prosta:

def ask(question) 
    yield(question) 
end 

proc = Proc.new { |question| puts question } 
new_pass = ask("Enter your new password: ", &proc) 
verify_pass = ask("Enter again to verify: ", &proc) 
2

Oto przykład, który spowoduje przedrostek indeksu metodą yield i dołączy indeks za pomocą metody call.

class Array 
    def alter_each! 
    self.each_with_index do |n, i| 
     self[i] = yield(n,i) 
    end 
    end 
    def modify_each!(add_one = true, &block) 
    self.each_with_index do |n, i| 
     j = (add_one) ? (i + 1) : i 
     self[i] = block.call(n,j) 
    end 
    end 
end 

a = ["dog", "cat", "cow"] 

a.alter_each! do |n, i| 
    "#{i}_#{n}" 
end 

a.modify_each! false do |n,i| 
    "#{n}_#{i}" 
end 

puts a 
Powiązane problemy