Jay-Ar Polidario
Jay-Ar Polidario

Reputation: 6603

How to pass all local variables when calling a method

I am wondering if there is an easy way to pass all local variables when calling a method, instead of passing them one by one as parameters. I want the following:

class Greeting
  def hello
    message = 'HELLO THERE!'
    language = 'English'
    say_greeting
  end

  def konnichiwa
    message = 'KONNICHIWA!'
    language = 'Japanese'
    say_greeting
  end

  private def say_greeting
    puts message
  end
end

Greeting.new.hello

to show HELLO THERE!. But it returns an error: NameError: undefined local variable or method 'message'.

I tried local_variables to get all local variables as an Array of symbols. But I can't seem to access the actual variables because there seemed to be no Ruby method like local_variable_get.

Background of the problem

In my Rails application, I have a controller having three update methods for different view files. All of them behave exactly the same (that they all will update a resource, show error if any, etc). Their only main difference are

  1. template to be rendered when unsuccessful
  2. redirect url when successful
  3. flash success message

I only have three variables, so it really is indeed easy to just pass them as parameters, but I am just wondering if there is an elegant solution to this.

Upvotes: 3

Views: 2565

Answers (3)

sawa
sawa

Reputation: 168121

Local variables are there to do precisely not what you are trying to do: encapsulate reference within a method definition. And instance variables are there to do precisely what you are trying to: sharing information between different method calls on a single object. Your use of local variable goes against that.

Use instance variables, not local variables.

If you insist on referencing local variables between methods, then here is a way:

class Greeting
  def hello
    message = 'HELLO THERE!'
    language = 'English'
    say_greeting(binding)
  end

  def konnichiwa
    message = 'KONNICHIWA!'
    language = 'Japanese'
    say_greeting(binding)
  end

  private def say_greeting b
    puts b.local_variable_get(:message)
  end
end

You can't make it without passing any arguments, but you can just pass a single binding argument, and refer all local variables from there.

Upvotes: 7

mhaseeb
mhaseeb

Reputation: 1779

Use instance variables. In your method say_greeting make sure you call the method hello first, otherwise the value of @message will be nil.

def hello
 @message = "Hello there"
end

def say_greeting
  hello #method call
  puts message
end

Upvotes: 1

devanand
devanand

Reputation: 5290

Make the message and language as instance variables. Then you can access them inside the private method.

class Greeting
  def hello
    @message = 'HELLO THERE!'
    @language = 'English'
    say_greeting
  end

  def konnichiwa
    @message = 'KONNICHIWA!'
    @language = 'Japanese'
    say_greeting
  end

  private 

  def say_greeting
    puts @message
  end
end

puts Greeting.new.hello

Upvotes: 1

Related Questions