Lincoln Mullen
Lincoln Mullen

Reputation: 6455

gets is not called within a Ruby method

In Ruby, I want to display the value of an instance variable to the user, then ask what the value should be using gets.chomp. Because I'll be doing this for several variables, I want to check the value with a method. My difficulty is that when I call gets in a method, the program runs without asking for user input.

Here is the relevant part of code:

class TagPodcast

  # ... Code to pull ID3v2 tags from MP3 file

  def inspect_tags
    puts "Title: " + @title
    set_tag(self.title)
  end

  def set_tag(tag)
    new_value = gets.chomp
    tag = new_value unless new_value == ""
  end

end

TagPodcast.new("myfile.mp3").inspect_tags

When I run the program, it prints Title: My Title Here but then exits without asking for input. What do I need to do to call gets?

Upvotes: 0

Views: 108

Answers (2)

Patrick Oscity
Patrick Oscity

Reputation: 54724

This (sligtly modified) program asks me for input as expected (just added accessor and constructor):

class TagPodcast
  attr_accessor :title

  def initialize(filename)
    @filename = filename
  end

  def inspect_tags
    puts "Title: " + @title
    set_tag(self.title)
  end

  def set_tag(tag)
    new_value = gets.chomp
    tag = new_value unless new_value == ""
  end
end

tp = TagPodcast.new("myfile.mp3")
tp.title = 'Dummy Title'

tp.inspect_tags

Your code has a different problem, though. Variables are passed into methods by value, not by reference, so this code will not behave as expected:

class Foo
  attr_accessor :variable

  def set_var(var)
    var = 'new value'
  end

  def bar
    self.variable = 'old value'
    set_var(self.variable)

    puts "@variable is now #{self.variable}"
  end
end

Foo.new.bar

this will print @variable is now old value. I can think of two ways around this. Either set the instance variable outside the method like so:

class Foo
  attr_accessor :variable

  def do_stuff
    'new value'
  end

  def bar
    self.variable = 'old value'
    self.variable = do_stuff

    puts "@variable is now #{self.variable}"
  end
end

Foo.new.bar

or use Ruby's powerful metaprogramming features and leverage instance_variable_set to dynamically set an instance variable by passing its name as a symbol:

class Foo
  attr_accessor :variable

  def set_var(var)
    instance_variable_set var, 'new value'
  end

  def bar
    self.variable = 'old value'
    set_var(:@variable)

    puts "@variable is now #{self.variable}"
  end
end

Foo.new.bar

As for your original question, we need to know more about the execution context. Probably STDIN is not what you expect it to be at execution time.

Upvotes: 2

GoZoner
GoZoner

Reputation: 70235

Ensure that you are getting input from standard input with:

STDIN.gets.chomp

or

$stdin.gets.chomp

Upvotes: 0

Related Questions