class Binding
Объекты класса Binding инкапсулируют контекст выполнения в определённой точке кода и сохраняют этот контекст для дальнейшего использования. Переменные, методы, значение self, и, возможно, блок итератора, доступные в этом контексте, сохраняются. Объекты Binding могут быть созданы с помощью Kernel#binding, и предоставляются в качестве аргумента обратного вызова Kernel#set_trace_func и экземплярам TracePoint.
Эти объекты связывания могут передаваться в качестве второго аргумента методу Kernel#eval, определяя окружение для выполнения.
class Demo
def initialize(n)
@secret = n
end
def get_binding
binding
end
end
k1 = Demo.new(99)
b1 = k1.get_binding
k2 = Demo.new(-3)
b2 = k2.get_binding
eval("@secret", b1) #=> 99
eval("@secret", b2) #=> -3
eval("@secret") #=> nil
Объекты Binding не имеют методов, специфичных для класса.
Методы публичного экземпляра
static VALUE
bind_eval(int argc, VALUE *argv, VALUE bindval)
{
VALUE args[4];
rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
args[1] = bindval;
return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */);
} Вычисляет выражение(я) Ruby в строке в контексте связывания. Если присутствуют необязательные параметры имя_файла и номер_строки, они будут использованы при сообщении об ошибках синтаксиса.
def get_binding(param)
binding
end
b = get_binding("hello")
b.eval("param") #=> "hello"
# File lib/irb.rb, line 980 def irb(show_code: true) IRB.setup(source_location[0], argv: []) workspace = IRB::WorkSpace.new(self) STDOUT.print(workspace.code_around_binding) if show_code binding_irb = IRB::Irb.new(workspace) binding_irb.context.irb_path = File.expand_path(source_location[0]) binding_irb.run(IRB.conf) binding_irb.debug_break end
Открывает сеанс IRB, где вызывается binding.irb, что позволяет осуществлять интерактивную отладку. Вы можете вызывать любые методы или переменные, доступные в текущем объёме, и изменять состояние, если необходимо.
Предположим, у вас есть файл Ruby с именем potato.rb содержащий следующий код:
class Potato
def initialize
@cooked = false
binding.irb
puts "Cooked potato: #{@cooked}"
end
end
Potato.new
Запуск ruby potato.rb откроет сеанс IRB, где вызывается binding.irb, и вы увидите следующее:
$ ruby potato.rb
From: potato.rb @ line 4 :
1: class Potato
2: def initialize
3: @cooked = false
=> 4: binding.irb
5: puts "Cooked potato: #{@cooked}"
6: end
7: end
8:
9: Potato.new
irb(#<Potato:0x00007feea1916670>):001:0> Вы можете вводить любой корректный код Ruby, который будет вычисляться в текущем контексте. Это позволяет отлаживать без многократного запуска кода:
irb(#<Potato:0x00007feea1916670>):001:0> @cooked => false irb(#<Potato:0x00007feea1916670>):002:0> self.class => Potato irb(#<Potato:0x00007feea1916670>):003:0> caller.first => ".../2.5.1/lib/ruby/2.5.0/irb/workspace.rb:85:in `eval'" irb(#<Potato:0x00007feea1916670>):004:0> @cooked = true => true
Вы можете выйти из сеанса IRB с помощью команды exit. Обратите внимание, что выход возобновит выполнение в том месте, где binding.irb приостановило его, как показано в выводе, напечатанном в стандартный вывод в этом примере:
irb(#<Potato:0x00007feea1916670>):005:0> exit Cooked potato: true
См. Использование IRB по адресу IRB для получения дополнительной информации.
static VALUE
bind_local_variable_defined_p(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
const rb_env_t *env;
if (!lid) return Qfalse;
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
return RBOOL(get_local_variable_ptr(&env, lid));
} Возвращает true если локальная переменная symbol существует.
def foo a = 1 binding.local_variable_defined?(:a) #=> true binding.local_variable_defined?(:b) #=> false end
Этот метод – сокращённый вариант следующего кода:
binding.eval("defined?(#{symbol}) == 'local-variable'")
static VALUE
bind_local_variable_get(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
const VALUE *ptr;
const rb_env_t *env;
if (!lid) goto undefined;
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if ((ptr = get_local_variable_ptr(&env, lid)) != NULL) {
return *ptr;
}
sym = ID2SYM(lid);
undefined:
rb_name_err_raise("local variable `%1$s' is not defined for %2$s",
bindval, sym);
UNREACHABLE_RETURN(Qundef);
} Возвращает значение локальной переменной symbol.
def foo a = 1 binding.local_variable_get(:a) #=> 1 binding.local_variable_get(:b) #=> NameError end
Этот метод – сокращённый вариант следующего кода:
binding.eval("#{symbol}")
static VALUE
bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val)
{
ID lid = check_local_id(bindval, &sym);
rb_binding_t *bind;
const VALUE *ptr;
const rb_env_t *env;
if (!lid) lid = rb_intern_str(sym);
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) {
/* not found. create new env */
ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
}
#if YJIT_STATS
rb_yjit_collect_binding_set();
#endif
RB_OBJ_WRITE(env, ptr, val);
return val;
} Set локальную переменную с именем symbol как obj.
def foo
a = 1
bind = binding
bind.local_variable_set(:a, 2) # set existing local variable `a'
bind.local_variable_set(:b, 3) # create new local variable `b'
# `b' exists only in binding
p bind.local_variable_get(:a) #=> 2
p bind.local_variable_get(:b) #=> 3
p a #=> 2
p b #=> NameError
end
Этот метод аналогичен следующему коду:
binding.eval("#{symbol} = #{obj}")
если obj может быть представлен в коде Ruby.
static VALUE
bind_local_variables(VALUE bindval)
{
const rb_binding_t *bind;
const rb_env_t *env;
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
return rb_vm_env_local_variables(env);
} Возвращает имена локальных переменных связывания в качестве символов.
def foo
a = 1
2.times do |n|
binding.local_variables #=> [:a, :n]
end
end
Этот метод – сокращённый вариант следующего кода:
binding.eval("local_variables")
static VALUE
bind_receiver(VALUE bindval)
{
const rb_binding_t *bind;
GetBindingPtr(bindval, bind);
return vm_block_self(&bind->block);
} Возвращает связанный получатель объекта связывания.
static VALUE
bind_location(VALUE bindval)
{
VALUE loc[2];
const rb_binding_t *bind;
GetBindingPtr(bindval, bind);
loc[0] = pathobj_path(bind->pathobj);
loc[1] = INT2FIX(bind->first_lineno);
return rb_ary_new4(2, loc);
} Возвращает имя файла и номер строки исходного кода Ruby объекта связывания.
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.