Давайте посмотрим, как внутреннее постоянное назначение работает. Следующий код извлекается из исходного архива ruby-1.9.3-p0. Сначала мы рассмотрим определение инструкции VM setconstant
(которая используется для назначения констант):
# /insns.def, line 239
DEFINE_INSN
setconstant
(ID id)
(VALUE val, VALUE cbase)
()
{
vm_check_if_namespace(cbase);
rb_const_set(cbase, id, val);
INC_VM_STATE_VERSION();
}
Здесь нет возможности разместить крюк в vm_check_if_namespace
или INC_VM_STATE_VERSION
. Итак, мы смотрим на rb_const_set
( variable.c: 1886 ), функцию, которая вызывается каждый раз, когда присваивается константа:
# /variable.c, line 1886
void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
VALUE visibility = CONST_PUBLIC;
# ...
check_before_mod_set(klass, id, val, "constant");
if (!RCLASS_CONST_TBL(klass)) {
RCLASS_CONST_TBL(klass) = st_init_numtable();
}
else {
# [snip], won't be called on first assignment
}
rb_vm_change_state();
ce = ALLOC(rb_const_entry_t);
ce->flag = (rb_const_flag_t)visibility;
ce->value = val;
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
}
Я удалил весь код, который даже не назывался при первом назначении константы внутри модуля. Затем я просмотрел все функции, вызываемые этой функцией, и не нашел ни единой точки, в которой мы могли бы поместить хук из кода Ruby. Это означает, что, если я что-то пропустил, это жесткая правда, что нет способа перехватить постоянное назначение (по крайней мере, в МРТ).
Обновление
Для пояснения: анонимный класс не волшебным образом получает новое имя, как только оно назначено (как правильно отмечено в ответе Эндрю). Скорее, имя константы вместе с идентификатором объекта класса хранится во внутренней таблице поиска констант Ruby. Если после этого запрашивается имя класса, теперь его можно преобразовать в правильное имя (а не просто Class:0xXXXXXXXX...
).
Таким образом, лучшее, что вы можете сделать, чтобы отреагировать на это назначение, это проверить name
класса в цикле фонового рабочего потока, пока он не будет равен nil
(что является огромной тратой ресурсов, IMHO ).