Ruby
TracePoint

Rubyで呼び出し元での変数名を取得する

TracePointを使う

def greet(greetings, time)
  unless greetings.key?(time)
    raise "[ERROR] #{time} is not in #{$var}"
  end

  puts greetings[time]
end

TracePoint.trace(:line) do |tp|
  $b = tp.binding
end

TracePoint.trace(:call) do |tp|
  return unless tp.method_id == :greet
  greetings = tp.binding.local_variable_get(:greetings)
  $var = $b.local_variables.detect {|v| $b.local_variable_get(v) == greetings }
end

english_greetings = {
  morning: 'Good morning!'
}

greet(english_greetings, :night)

binding_of_callerを使う

require 'binding_of_caller'

def greet(greetings, time)
  unless greetings.key?(time)
    b = binding.of_caller(1)
    var = b.local_variables.detect {|v| b.local_variable_get(v) == greetings }
    raise "[ERROR] #{time} is not in #{var}"
  end

  puts greetings[time]
end

english_greetings = {
  morning: 'Good morning!'
}

greet(english_greetings, :night)

binding_ninjaを使う

require 'binding_ninja'

self.class.extend BindingNinja

def greet(b, greetings, time)
  unless greetings.key?(time)
    var = b.local_variables.detect {|v| b.local_variable_get(v) == greetings }
    raise "[ERROR] #{time} is not in #{var}"
  end

  puts greetings[time]
end

self.class.class_eval { auto_inject_binding :greet }

english_greetings = {
  morning: 'Good morning!'
}

greet(english_greetings, :night)