views:

1556

answers:

6

I'm trying to do Ruby password input with the Highline gem and since I have the user input the password twice, I'd like to eliminate the duplication on the blocks I'm passing in. For example, a simple version of what I'm doing right now is:

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

And what I'd like to change it to is something like this:

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

Which unfortunately doesn't work. What's the correct way to do this?

+1  A: 

This article is probably what you are looking for.

Cory Foy
The article had a lot of helpful info in it, but unfortunately nothing about this particular issue. Thanks though!
Chris Bunch
A: 

I don't think the language supports a construct like this. The only way I can see to generalize this in any way is:

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) }

It doesn't really shorten the code, though it does remove some duplication--if you wanted to do more than set prompt.echo to false, you'd only have to add code in one place.

Lucas Oman
+1  A: 
   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)}
David Nehme
That did it! Thanks for the quick reply!
Chris Bunch
+12  A: 

The code by David will work fine, but this is an easier and shorter solution:

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

You can also use the pound sign to assign a block to a variable when defining a method:

def ask(msg, &block)
  puts block.inspect
end
Adam Byrtek
Chris Bunch
Adam Byrtek
Chris Bunch
+1  A: 

This is how you should do it, clean and simple:

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)
Honza
A: 

Here is an example that will prefix the index with the yield method and append the index with the call method.

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
jspooner