Spec-Zone.ru › Ruby 4.0

модуль Kernel

Модуль Kernel включается в класс Object, поэтому его методы доступны в каждом объекте Ruby.

Методы экземпляра Kernel описаны в классе Object, а методы модуля описаны здесь. Эти методы вызываются без получателя, поэтому их можно вызывать в функциональной форме:

sprintf "%.1f", 1.234 #=> "1.2"

Что здесь есть

Модуль Kernel предоставляет методы, полезные для:

  • преобразования

  • получения сведений

  • завершения работы

  • исключений

  • ввода-вывода

  • процедур Proc

  • трассировки

  • подпроцессов

  • загрузки

  • передачи управления блоку

  • случайных значений

  • прочего

Преобразование

  • Array: возвращает Array на основе заданного аргумента.

  • Complex: возвращает Complex на основе заданных аргументов.

  • Float: возвращает Float на основе заданных аргументов.

  • Hash: возвращает Hash на основе заданного аргумента.

  • Integer: возвращает Integer на основе заданных аргументов.

  • Rational: возвращает Rational на основе заданных аргументов.

  • String: возвращает String на основе заданного аргумента.

Получение сведений

  • __callee__: возвращает имя, под которым был вызван текущий метод, в виде символа.

  • __dir__: возвращает путь к каталогу, из которого вызван текущий метод.

  • __method__: возвращает имя текущего метода в виде символа.

  • autoload?: возвращает файл, который будет загружен при обращении к заданному модулю.

  • binding: возвращает Binding для контекста в точке вызова.

  • block_given?: возвращает true, если вызывающему методу был передан блок.

  • caller: возвращает текущий стек вызовов в виде массива строк.

  • caller_locations: возвращает текущий стек вызовов в виде массива объектов Thread::Backtrace::Location.

  • class: возвращает класс self.

  • frozen?: возвращает информацию о том, заморожен ли self.

  • global_variables: возвращает массив глобальных переменных в виде символов.

  • local_variables: возвращает массив локальных переменных в виде символов.

  • test: выполняет указанные проверки для заданного файла или пары файлов.

Завершение работы

  • abort: завершает текущий процесс после вывода заданных аргументов.

  • at_exit: выполняет заданный блок при завершении процесса.

  • exit: завершает текущий процесс после вызова всех зарегистрированных обработчиков at_exit.

  • exit!: завершает текущий процесс, не вызывая зарегистрированные обработчики at_exit.

Исключения

  • catch: выполняет заданный блок, возможно перехватывая переданный объект.

  • raise (псевдоним — fail): вызывает исключение на основе заданных аргументов.

  • throw: возвращает управление из активного блока catch, ожидающего заданную метку.

Ввод-вывод

  • ::pp: выводит заданные объекты в удобочитаемом виде.

  • gets: возвращает следующую строку из текущего ввода и присваивает её $_.

  • open: создаёт объект IO, связанный с заданным потоком, файлом или подпроцессом.

  • p: выводит результат inspect заданных объектов в стандартный вывод.

  • print: выводит заданные объекты в стандартный вывод без перевода строки.

  • printf: выводит строку, полученную применением заданной строки формата к дополнительным аргументам.

  • putc: эквивалентен $stdout.putc(object) для заданного объекта.

  • puts: эквивалентен $stdout.puts(*objects) для заданных объектов.

  • readline: аналогичен gets, но вызывает исключение при достижении конца файла.

  • readlines: возвращает массив оставшихся строк из текущего ввода.

  • select: то же, что и IO.select.

Процедуры Proc

  • lambda: возвращает лямбда-процедуру для заданного блока.

  • proc: возвращает новый объект Proc; эквивалентен Proc.new.

Трассировка

  • set_trace_func: назначает заданную процедуру обработчиком трассировки или отключает трассировку, если передано nil.

  • trace_var: начинает отслеживать присваивания заданной глобальной переменной.

  • untrace_var: прекращает отслеживать присваивания заданной глобальной переменной.

Подпроцессы

  • ‘command`: возвращает стандартный вывод команды command, запущенной в подоболочке.

  • exec: заменяет текущий процесс новым процессом.

  • fork: разветвляет текущий процесс на два процесса.

  • spawn: выполняет заданную команду и возвращает её pid, не дожидаясь завершения.

  • system: выполняет заданную команду в подоболочке.

Загрузка

  • autoload: регистрирует заданный файл для загрузки при первом обращении к заданной константе.

  • load: загружает заданный файл Ruby.

  • require: загружает заданный файл Ruby, если он ещё не был загружен.

  • require_relative: загружает файл Ruby по пути относительно вызывающего файла, если он ещё не был загружен.

Передача управления блоку

  • tap: передаёт self заданному блоку; возвращает self.

  • then (псевдоним — yield_self): передаёт self блоку и возвращает результат его выполнения.

Случайные значения

  • rand: возвращает псевдослучайное число с плавающей точкой строго между 0.0 и 1.0.

  • srand: инициализирует генератор псевдослучайных чисел заданным числом.

Прочее

  • eval: вычисляет заданную строку как код Ruby.

  • loop: многократно выполняет заданный блок.

  • sleep: приостанавливает текущий поток на заданное число секунд.

  • sprintf (псевдоним — format): возвращает строку, полученную применением заданной строки формата к дополнительным аргументам.

  • syscall: выполняет системный вызов операционной системы.

  • trap: задаёт обработку системных сигналов.

  • warn: выводит предупреждение на основе заданных сообщений и параметров.

Открытые методы класса

Pathname (path) Показать исходный код
# File pathname_builtin.rb, line 1167
def Pathname(path) # :doc:
  return path if Pathname === path
  Pathname.new(path)
end

Создаёт объект Pathname.

URI (uri) Показать исходный код
# File lib/uri/common.rb, line 911
def URI(uri)
  if uri.is_a?(URI::Generic)
    uri
  elsif uri = String.try_convert(uri)
    URI.parse(uri)
  else
    raise ArgumentError,
      "bad argument (expected URI object or URI string)"
  end
end

Возвращает объект URI, созданный на основе заданного uri, которым может быть строка URI или существующий объект URI:

require 'uri'
# Returns a new URI.
uri = URI('http://github.com/ruby/ruby')
# => #<URI::HTTP http://github.com/ruby/ruby>
# Returns the given URI.
URI(uri)
# => #<URI::HTTP http://github.com/ruby/ruby>

Чтобы использовать этот метод, необходимо подключить ‘uri’.

pp (*objs) Показать исходный код
# File lib/pp.rb, line 731
def pp(*objs)
  objs.each {|obj|
    PP.pp(obj)
  }
  objs.size <= 1 ? objs.first : objs
end

выводит аргументы в удобочитаемом виде.

pp возвращает аргумент или аргументы.

Открытые методы экземпляра

__callee__ → symbol Показать исходный код
static VALUE
rb_f_callee_name(VALUE _)
{
    ID fname = prev_frame_callee(); /* need *callee* ID */

    if (fname) {
        return ID2SYM(fname);
    }
    else {
        return Qnil;
    }
}

Возвращает имя вызываемого текущего метода в виде Symbol. При вызове вне метода возвращает nil.

__dir__ → string Показать исходный код
static VALUE
f_current_dirname(VALUE _)
{
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        return Qnil;
    }
    base = rb_file_dirname(base);
    return base;
}

Возвращает канонический абсолютный путь к каталогу файла, из которого вызван этот метод. Это означает, что символические ссылки в пути разрешаются. Если __FILE__ равен nil, возвращается nil. Возвращаемое значение равно File.dirname(File.realpath(__FILE__)).

__method__ → symbol Показать исходный код
static VALUE
rb_f_method_name(VALUE _)
{
    ID fname = prev_frame_func(); /* need *method* ID */

    if (fname) {
        return ID2SYM(fname);
    }
    else {
        return Qnil;
    }
}

Возвращает имя текущего метода в месте его определения в виде Symbol. При вызове вне метода возвращает nil.

`command` → string Показать исходный код
static VALUE
rb_f_backquote(VALUE obj, VALUE str)
{
    VALUE port;
    VALUE result;
    rb_io_t *fptr;

    StringValue(str);
    rb_last_status_clear();
    port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
    if (NIL_P(port)) return rb_str_new(0,0);

    GetOpenFile(port, fptr);
    result = read_all(fptr, remain_size(fptr), Qnil);
    rb_io_close(port);
    rb_io_fptr_cleanup_all(fptr);
    RB_GC_GUARD(port);

    return result;
}

Возвращает вывод $stdout, полученный при выполнении command во вложенной оболочке; устанавливает глобальную переменную $? в состояние процесса.

Этот метод может быть уязвим с точки зрения безопасности, если вызвать его с ненадежными входными данными; см. Инъекция команд.

Примеры:

$ `date`                 # => "Wed Apr  9 08:56:30 CDT 2003\n"
$ `echo oops && exit 99` # => "oops\n"
$ $?                     # => #<Process::Status: pid 17088 exit 99>
$ $?.exitstatus          # => 99

Встроенный синтаксис %x{...} использует этот метод.

Array(object) → object or new_array Показать исходный код
static VALUE
rb_f_array(VALUE obj, VALUE arg)
{
    return rb_Array(arg);
}

Возвращает массив, преобразованный из object.

Сначала пытается преобразовать object в массив с помощью to_ary, затем — с помощью to_a:

Array([0, 1, 2])        # => [0, 1, 2]
Array({foo: 0, bar: 1}) # => [[:foo, 0], [:bar, 1]]
Array(0..4)             # => [0, 1, 2, 3, 4]

Если object преобразовать не удается, возвращает object в массиве, [object]:

Array(:foo)             # => [:foo]
Complex(real, imag = 0, exception: true) → complex or nil Показать исходный код
Complex(s, exception: true) → complex or nil
static VALUE
nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
{
    VALUE a1, a2, opts = Qnil;
    int raise = TRUE;

    if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
        a2 = Qundef;
    }
    if (!NIL_P(opts)) {
        raise = rb_opts_exception_p(opts, raise);
    }
    if (argc > 0 && CLASS_OF(a1) == rb_cComplex && UNDEF_P(a2)) {
        return a1;
    }
    return nucomp_convert(rb_cComplex, a1, a2, raise);
}

Если аргументы допустимы, возвращает новый объект Complex; в противном случае вызывает исключение, если exception равно true, иначе возвращает nil.

Если аргументы real и imag имеют тип Numeric, возвращает Complex.rect(real, imag), если аргументы допустимы.

Если аргумент s является строкой, возвращает новый объект Complex, если аргумент допустим; строка может содержать:

  • Одну или две числовые подстроки, каждая из которых задает значение типа Complex, Float, Integer, Numeric или Rational, задавая прямоугольные координаты:

    • Числовые подстроки действительной и мнимой частей, разделенные знаком (с завершающим символом 'i'):

      Complex('1+2i')  # => (1+2i)
      Complex('+1+2i') # => (1+2i)
      Complex('+1-2i') # => (1-2i)
      Complex('-1+2i') # => (-1+2i)
      Complex('-1-2i') # => (-1-2i)
      
    • Строка только с действительной частью (без завершающего символа 'i'):

      Complex('1')  # => (1+0i)
      Complex('+1') # => (1+0i)
      Complex('-1') # => (-1+0i)
      
    • Строка только с мнимой частью (с завершающим символом 'i'):

      Complex('1i')  # => (0+1i)
      Complex('+1i') # => (0+1i)
      Complex('-1i') # => (0-1i)
      
  • Рациональные подстроки действительной и мнимой частей, разделенные символом @, каждая из которых задает значение типа Rational, задавая полярные координаты:

    Complex('1/2@3/4')   # => (0.36584443443691045+0.34081938001166706i)
    Complex('+1/2@+3/4') # => (0.36584443443691045+0.34081938001166706i)
    Complex('+1/2@-3/4') # => (0.36584443443691045-0.34081938001166706i)
    Complex('-1/2@+3/4') # => (-0.36584443443691045-0.34081938001166706i)
    Complex('-1/2@-3/4') # => (-0.36584443443691045+0.34081938001166706i)
    
Float(arg, exception: true) → float or nil Показать исходный код
# File kernel.rb, line 194
def Float(arg, exception: true)
  if Primitive.mandatory_only?
    Primitive.rb_f_float1(arg)
  else
    Primitive.rb_f_float(arg, exception)
  end
end

Возвращает arg, преобразованный в число с плавающей точкой. Типы Numeric преобразуются напрямую; за исключением String и nil, остальные преобразуются с помощью arg.to_f. При преобразовании String с недопустимыми символами возникает ArgumentError. Преобразование nil вызывает TypeError. Исключения можно подавить, передав exception: false.

Float(1)                 #=> 1.0
Float("123.456")         #=> 123.456
Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring"
Float(nil)               #=> TypeError: can't convert nil into Float
Float("123.0_badstring", exception: false)  #=> nil
Hash(object) → object or new_hash Показать исходный код
static VALUE
rb_f_hash(VALUE obj, VALUE arg)
{
    return rb_Hash(arg);
}

Возвращает хеш, преобразованный из object.

  • Если object — это:

    • Хеш — возвращает object.

    • Пустой массив или nil — возвращает пустой хеш.

  • Иначе, если object.to_hash возвращает хеш, возвращает этот хеш.

  • В противном случае возвращает TypeError.

Примеры:

Hash({foo: 0, bar: 1}) # => {:foo=>0, :bar=>1}
Hash(nil)              # => {}
Hash([])               # => {}
Integer(object, base = 0, exception: true) → integer or nil Показать исходный код
# File kernel.rb, line 287
def Integer(arg, base = 0, exception: true)
  if Primitive.mandatory_only?
    Primitive.rb_f_integer1(arg)
  else
    Primitive.rb_f_integer(arg, base, exception)
  end
end

Возвращает целое число, преобразованное из object.

Сначала пытается преобразовать object в целое число с помощью to_int, затем — с помощью to_i; исключения описаны ниже.

Если base не равно нулю, object должно быть строкой или объектом, преобразуемым в строку.

Числовые объекты

Если передан аргумент-целое число object, возвращает object:

Integer(1)                # => 1
Integer(-1)               # => -1

Если передан аргумент с плавающей точкой object, возвращает object, усеченное до целого числа:

Integer(1.9)              # => 1  # Rounds toward zero.
Integer(-1.9)             # => -1 # Rounds toward zero.

Строковые объекты

Если передан строковый аргумент object и нулевое значение base, возвращает object, преобразованное в целое число в системе счисления с основанием 10:

Integer('100')    # => 100
Integer('-100')   # => -100

Если base не равно нулю, строка object может содержать в начале символы, задающие фактическое основание системы счисления (индикатор основания):

Integer('0100')  # => 64  # Leading '0' specifies base 8.
Integer('0b100') # => 4   # Leading '0b' specifies base 2.
Integer('0x100') # => 256 # Leading '0x' specifies base 16.

Если передано положительное значение base (в диапазоне 2..36), возвращает object, преобразованное в целое число в указанной системе счисления:

Integer('100', 2)   # => 4
Integer('100', 8)   # => 64
Integer('-100', 16) # => -256

Если передано отрицательное значение base (в диапазоне -36..-2), возвращает object, преобразованное с учетом индикатора основания, если он присутствует, или base:

Integer('0x100', -2)   # => 256
Integer('100', -2)     # => 4
Integer('0b100', -8)   # => 4
Integer('100', -8)     # => 64
Integer('0o100', -10)  # => 64
Integer('100', -10)    # => 100

base -1 эквивалентно случаю -10.

При преобразовании строк допускаются окружающие пробелы и символы подчеркивания внутри строки, которые игнорируются:

Integer(' 100 ')      # => 100
Integer('-1_0_0', 16) # => -256

Другие классы

Примеры с object различных других классов:

Integer(Rational(9, 10)) # => 0  # Rounds toward zero.
Integer(Complex(2, 0))   # => 2  # Imaginary part must be zero.
Integer(Time.now)        # => 1650974042

Ключевые аргументы

Если необязательный ключевой аргумент exception задан как true (значение по умолчанию):

  • Вызывает TypeError, если object не отвечает на to_int или to_i.

  • Вызывает TypeError, если object равен nil.

  • Вызывает ArgumentError, если object — недопустимая строка.

Если exception задан как false, исключение любого типа подавляется и возвращается nil.

Rational(x, y, exception: true) → rational or nil Показать исходный код
Rational(arg, exception: true) → rational or nil
static VALUE
nurat_f_rational(int argc, VALUE *argv, VALUE klass)
{
    VALUE a1, a2, opts = Qnil;
    int raise = TRUE;

    if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
        a2 = Qundef;
    }
    if (!NIL_P(opts)) {
        raise = rb_opts_exception_p(opts, raise);
    }
    return nurat_convert(rb_cRational, a1, a2, raise);
}

Возвращает x/y или arg в виде Rational.

Rational(2, 3)   #=> (2/3)
Rational(5)      #=> (5/1)
Rational(0.5)    #=> (1/2)
Rational(0.3)    #=> (5404319552844595/18014398509481984)

Rational("2/3")  #=> (2/3)
Rational("0.3")  #=> (3/10)

Rational("10 cents")  #=> ArgumentError
Rational(nil)         #=> TypeError
Rational(1, nil)      #=> TypeError

Rational("10 cents", exception: false)  #=> nil

Синтаксис строковой формы:

string form = extra spaces , rational , extra spaces ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ;

См. также String#to_r.

String(object) → object or new_string Показать исходный код
static VALUE
rb_f_string(VALUE obj, VALUE arg)
{
    return rb_String(arg);
}

Возвращает строку, преобразованную из object.

Сначала пытается преобразовать object в строку с помощью to_str, затем — с помощью to_s:

String([0, 1, 2])        # => "[0, 1, 2]"
String(0..5)             # => "0..5"
String({foo: 0, bar: 1}) # => "{foo: 0, bar: 1}"

Вызывает TypeError, если object нельзя преобразовать в строку.

abort Показать исходный код
abort(msg = nil)
static VALUE
f_abort(int c, const VALUE *a, VALUE _)
{
    rb_f_abort(c, a);
    UNREACHABLE_RETURN(Qnil);
}

Немедленно завершает выполнение, фактически вызывая Kernel.exit(false).

Если передан строковый аргумент msg, он выводится в STDERR перед завершением; если же было вызвано исключение, выводятся его сообщение и трассировка стека.

at_exit { block } → proc Показать исходный код
static VALUE
rb_f_at_exit(VALUE _)
{
    VALUE proc;

    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "called without a block");
    }
    proc = rb_block_proc();
    rb_set_end_proc(rb_call_end_proc, proc);
    return proc;
}

Преобразует block в объект Proc (и, следовательно, связывает его в точке вызова) и регистрирует его для выполнения при завершении программы. Если зарегистрировано несколько обработчиков, они выполняются в порядке, обратном порядку регистрации.

def do_at_exit(str1)
  at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit

выводит:

goodbye cruel world
autoload(const, filename) → nil Показать исходный код
static VALUE
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
{
    VALUE klass = rb_class_real(rb_vm_cbase());
    if (!klass) {
        rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
    }
    return rb_mod_autoload(klass, sym, file);
}

Регистрирует filename для загрузки (с помощью Kernel::require) при первом обращении к const (который может быть String или символом).

autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")

Если для const уже зарегистрирована автозагрузка, имя загружаемого файла заменяется на filename. Если const определен, но не как автозагружаемый, метод ничего не делает.

Файлы, которые в данный момент загружаются, нельзя регистрировать для автозагрузки.

autoload?(name, inherit=true) → String or nil Показать исходный код
static VALUE
rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
{
    /* use rb_vm_cbase() as same as rb_f_autoload. */
    VALUE klass = rb_vm_cbase();
    if (NIL_P(klass)) {
        return Qnil;
    }
    return rb_mod_autoload_p(argc, argv, klass);
}

Возвращает filename для загрузки, если name зарегистрировано как autoload в текущем пространстве имен или одном из его предков.

autoload(:B, "b")
autoload?(:B)            #=> "b"

module C
  autoload(:D, "d")
  autoload?(:D)          #=> "d"
  autoload?(:B)          #=> nil
end

class E
  autoload(:F, "f")
  autoload?(:F)          #=> "f"
  autoload?(:B)          #=> "b"
end
binding → a_binding Показать исходный код
static VALUE
rb_f_binding(VALUE self)
{
    return rb_binding_new();
}

Возвращает объект Binding, описывающий привязки переменных и методов в точке вызова. Этот объект можно использовать при вызове Binding#eval, чтобы выполнить вычисляемую команду в этом окружении или получить его локальные переменные.

class User
  def initialize(name, position)
    @name = name
    @position = position
  end

  def get_binding
    binding
  end
end

user = User.new('Joan', 'manager')
template = '{name: @name, position: @position}'

# evaluate template in context of the object
eval(template, user.get_binding)
#=> {:name=>"Joan", :position=>"manager"}

Для доступа к переменным, имена которых совпадают с зарезервированными ключевыми словами Ruby, можно использовать Binding#local_variable_get:

# This is valid parameter declaration, but `if` parameter can't
# be accessed by name, because it is a reserved word.
def validate(field, validation, if: nil)
  condition = binding.local_variable_get('if')
  return unless condition

  # ...Some implementation ...
end

validate(:name, :empty?, if: false) # skips validation
validate(:name, :empty?, if: true) # performs validation
block_given? → true or false Показать исходный код
static VALUE
rb_f_block_given_p(VALUE _)
{
    rb_execution_context_t *ec = GET_EC();
    rb_control_frame_t *cfp = ec->cfp;
    cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));

    return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE);
}

Возвращает true, если yield выполнит блок в текущем контексте. Форма iterator? считается несколько устаревшей.

def try
  if block_given?
    yield
  else
    "no block"
  end
end
try                  #=> "no block"
try { "hello" }      #=> "hello"
try do "hello" end   #=> "hello"
callcc {|cont| block } → obj Показать исходный код
static VALUE
rb_callcc(VALUE self)
{
    volatile int called;
    volatile VALUE val = cont_capture(&called);

    if (called) {
        return val;
    }
    else {
        return rb_yield(val);
    }
}

Создает объект Continuation и передает его связанному блоку. Перед использованием этого метода необходимо выполнить require 'continuation'. Выполнение cont.call приводит к возврату из callcc (как и достижение конца блока). Возвращаемое callcc значение — это значение блока или значение, переданное в cont.call. Подробнее см. класс Continuation. Также см. Kernel#throw — альтернативный способ раскрутки стека вызовов.

caller(start=1, length=nil) → array or nil Показать исходный код
caller(range) → array or nil
static VALUE
rb_f_caller(int argc, VALUE *argv, VALUE _)
{
    return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
}

Возвращает текущий стек выполнения — массив со строками формата file:line или file:line: in `method'.

Необязательный параметр start задает количество начальных записей стека, которые следует пропустить сверху стека.

Второй необязательный параметр length позволяет ограничить количество возвращаемых записей стека.

Возвращает nil, если значение start превышает размер текущего стека выполнения.

В качестве альтернативы можно передать диапазон; тогда будет возвращен массив, содержащий записи из указанного диапазона.

def a(skip)
  caller(skip)
end
def b(skip)
  a(skip)
end
def c(skip)
  b(skip)
end
c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
c(2)   #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
c(3)   #=> ["prog:13:in `<main>'"]
c(4)   #=> []
c(5)   #=> nil
caller_locations(start=1, length=nil) → array or nil Показать исходный код
caller_locations(range) → array or nil
static VALUE
rb_f_caller_locations(int argc, VALUE *argv, VALUE _)
{
    return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
}

Возвращает текущий стек выполнения — массив с объектами расположения из трассировки стека.

Дополнительные сведения см. в разделе Thread::Backtrace::Location.

Необязательный параметр start задает количество начальных записей стека, которые следует пропустить сверху стека.

Второй необязательный параметр length позволяет ограничить количество возвращаемых записей стека.

Возвращает nil, если значение start превышает размер текущего стека выполнения.

В качестве альтернативы можно передать диапазон; тогда будет возвращен массив, содержащий записи из указанного диапазона.

catch([tag]) {|tag| block } → obj Показать исходный код
static VALUE
rb_f_catch(int argc, VALUE *argv, VALUE self)
{
    VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
    return rb_catch_obj(tag, catch_i, 0);
}

catch выполняет свой блок. Если throw не вызывается, блок выполняется обычным образом, а catch возвращает значение последнего вычисленного выражения.

catch(1) { 123 }            # => 123

Если вызывается throw(tag2, val), Ruby ищет выше по стеку блок catch, у которого tag имеет то же значение object_id, что и tag2. При обнаружении такого блока его выполнение прекращается, и он возвращает val (или nil, если второй аргумент не был передан в throw).

catch(1) { throw(1, 456) }  # => 456
catch(1) { throw(1) }       # => nil

Если в качестве первого аргумента передано tag, catch передает его блоку как параметр.

catch(1) {|x| x + 2 }       # => 3

Если tag не задан, catch передает блоку в качестве параметра новый уникальный объект (как при вызове Object.new). Этот объект можно затем использовать как аргумент для throw; он будет соответствовать нужному блоку catch.

catch do |obj_A|
  catch do |obj_B|
    throw(obj_B, 123)
    puts "This puts is not reached"
  end

  puts "This puts is displayed"
  456
end

# => 456

catch do |obj_A|
  catch do |obj_B|
    throw(obj_A, 123)
    puts "This puts is still not reached"
  end

  puts "Now this puts is also not reached"
  456
end

# => 123
chomp → $_ Показать исходный код
chomp(string) → $_
static VALUE
rb_f_chomp(int argc, VALUE *argv, VALUE _)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
    rb_lastline_set(str);
    return str;
}

Эквивалентно $_ = $_.chomp(string). См. String#chomp. Доступно только при указании параметра командной строки -p/-n.

chop → $_ Показать исходный код
chop → $_
static VALUE
rb_f_chop(VALUE _)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
    rb_lastline_set(str);
    return str;
}

Эквивалентно ($_.dup).chop!, за исключением того, что nil никогда не возвращается. См. String#chop!. Доступно только при указании параметра командной строки -p/-n.

class → class Показать исходный код
# File kernel.rb, line 18
def class
  Primitive.attr! :leaf
  Primitive.cexpr! 'rb_obj_class_must(self)'
end

Возвращает класс obj. Этот метод всегда необходимо вызывать с явным получателем, поскольку class также является зарезервированным словом в Ruby.

1.class      #=> Integer
self.class   #=> Object
clone(freeze: nil) → an_object Показать исходный код
# File kernel.rb, line 47
def clone(freeze: nil)
  Primitive.rb_obj_clone2(freeze)
end

Создает поверхностную копию obj: копируются переменные экземпляра obj, но не объекты, на которые они ссылаются. clone копирует состояние замороженности значения obj, если только для ключевого аргумента :freeze не задано значение false или true. См. также обсуждение метода Object#dup.

class Klass
   attr_accessor :str
end
s1 = Klass.new      #=> #<Klass:0x401b3a38>
s1.str = "Hello"    #=> "Hello"
s2 = s1.clone       #=> #<Klass:0x401b3998 @str="Hello">
s2.str[1,4] = "i"   #=> "i"
s1.inspect          #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
s2.inspect          #=> "#<Klass:0x401b3998 @str=\"Hi\">"

Этот метод может вести себя по-разному в зависимости от класса. Если это так, такое поведение будет описано в документации метода #initialize_copy этого класса.

eval(string [, binding [, filename [,lineno]]]) → obj Показать исходный код
VALUE
rb_f_eval(int argc, const VALUE *argv, VALUE self)
{
    VALUE src, scope, vfile, vline;
    VALUE file = Qundef;
    int line = 1;

    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
    StringValue(src);
    if (argc >= 3) {
        StringValue(vfile);
    }
    if (argc >= 4) {
        line = NUM2INT(vline);
    }

    if (!NIL_P(vfile))
        file = vfile;

    if (NIL_P(scope))
        return eval_string_with_cref(self, src, NULL, file, line);
    else
        return eval_string_with_scope(scope, src, file, line);
}

Вычисляет выражение или выражения Ruby в string. Если передан binding, который должен быть объектом Binding, вычисление выполняется в его контексте. Если указаны необязательные параметры filename и lineno, они используются при сообщении о синтаксических ошибках.

def get_binding(str)
  return binding
end
str = "hello"
eval "str + ' Fred'"                      #=> "hello Fred"
eval "str + ' Fred'", get_binding("bye")  #=> "bye Fred"
exec([env, ] command_line, options = {}) Показать исходный код
exec([env, ] exe_path, *args, options = {})
static VALUE
f_exec(int c, const VALUE *a, VALUE _)
{
    rb_f_exec(c, a);
    UNREACHABLE_RETURN(Qnil);
}

Заменяет текущий процесс одним из следующих способов:

  • Передает строку command_line оболочке.

  • Запускает исполняемый файл по пути exe_path.

Этот метод может быть уязвим с точки зрения безопасности, если вызвать его с ненадежными входными данными; см. Инъекция команд.

Новый процесс создается с помощью системного вызова exec; он может унаследовать часть окружения вызывающей программы (возможно, включая открытые файловые дескрипторы).

Аргумент env, если он указан, представляет собой хеш, который влияет на ENV нового процесса; см. Окружение выполнения.

Аргумент options представляет собой хеш параметров нового процесса; см. Параметры выполнения.

Первый обязательный аргумент — одно из следующего:

  • command_line, если это строка, начинающаяся с зарезервированного слова оболочки или специальной встроенной команды либо содержащая один или несколько метасимволов.

  • exe_path в остальных случаях.

Аргумент command_line

Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова оболочки или специальной встроенной команды либо содержать метасимволы:

exec('if true; then echo "Foo"; fi') # Shell reserved word.
exec('exit')                         # Built-in.
exec('date > date.tmp')              # Contains meta character.

Командная строка также может содержать аргументы и параметры команды:

exec('echo "Foo"')

Вывод:

Foo

Подробные сведения об оболочке см. в разделе Оболочка выполнения.

Если новый процесс не удалось запустить, возникает исключение.

Аргумент exe_path

Аргумент exe_path — это одно из следующего:

  • Строковый путь к запускаемому исполняемому файлу.

  • Массив из двух элементов, содержащий путь к исполняемому файлу и строку, используемую в качестве имени выполняемого процесса.

Пример:

exec('/usr/bin/date')

Вывод:

Sat Aug 26 09:38:00 AM CDT 2023

Ruby вызывает исполняемый файл напрямую. В этой форме оболочка не используется; см. раздел Аргументы args с описанием ограничений.

exec('doesnt_exist') # Raises Errno::ENOENT

Если указан один или несколько аргументов args, каждый из них является аргументом или параметром, передаваемым исполняемому файлу:

exec('echo', 'C*')
exec('echo', 'hello', 'world')

Вывод:

C*
hello world

Если новый процесс не удалось запустить, возникает исключение.

exit(status = true) Показать исходный код
exit(status = true)
static VALUE
f_exit(int c, const VALUE *a, VALUE _)
{
    rb_f_exit(c, a);
    UNREACHABLE_RETURN(Qnil);
}

Запускает завершение скрипта Ruby, возбуждая SystemExit; исключение можно перехватить. Возвращает код завершения status базовой операционной системе.

Значения true и false для аргумента status указывают соответственно на успех и неудачу; значения целых чисел зависят от системы.

Пример:

begin
  exit
  puts 'Never get here.'
rescue SystemExit
  puts 'Rescued a SystemExit exception.'
end
puts 'After begin block.'

Вывод:

Rescued a SystemExit exception.
After begin block.

Непосредственно перед окончательным завершением Ruby выполняет все процедуры at-exit (см. Kernel::at_exit) и финализаторы всех объектов (см. ObjectSpace::define_finalizer).

Пример:

at_exit { puts 'In at_exit function.' }
ObjectSpace.define_finalizer('string', proc { puts 'In finalizer.' })
exit

Вывод:

In at_exit function.
In finalizer.
exit!(status = false) Показать исходный код
exit!(status = false)
static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
    int istatus;

    if (rb_check_arity(argc, 0, 1) == 1) {
        istatus = exit_status_code(argv[0]);
    }
    else {
        istatus = EXIT_FAILURE;
    }
    _exit(istatus);

    UNREACHABLE_RETURN(Qnil);
}

Немедленно завершает процесс; обработчики завершения не вызываются. Возвращает код завершения status базовой операционной системе.

Process.exit!(true)

Значения true и false для аргумента status указывают соответственно на успех и неудачу; значения целых чисел зависят от системы.

fail
Псевдоним для: raise
fork { ... } → integer or nil Показать исходный код
fork → integer or nil
static VALUE
rb_f_fork(VALUE obj)
{
    rb_pid_t pid;

    pid = rb_call_proc__fork();

    if (pid == 0) {
        if (rb_block_given_p()) {
            int status;
            rb_protect(rb_yield, Qundef, &status);
            ruby_stop(status);
        }
        return Qnil;
    }

    return PIDT2NUM(pid);
}

Создаёт дочерний процесс.

Если передан блок, выполняет его в дочернем процессе; при выходе из блока дочерний процесс завершается с нулевым статусом:

puts "Before the fork: #{Process.pid}"
fork do
  puts "In the child process: #{Process.pid}"
end                   # => 382141
puts "After the fork: #{Process.pid}"

Вывод:

Before the fork: 420496
After the fork: 420496
In the child process: 420520

Если блок не передан, вызов fork возвращает значение дважды:

  • Один раз в родительском процессе, возвращая pid дочернего процесса.

  • Один раз в дочернем процессе, возвращая nil.

Пример:

puts "This is the first line before the fork (pid #{Process.pid})"
puts fork
puts "This is the second line after the fork (pid #{Process.pid})"

Вывод:

This is the first line before the fork (pid 420199)
420223
This is the second line after the fork (pid 420199)

This is the second line after the fork (pid 420223)

В обоих случаях дочерний процесс может завершиться с помощью Kernel.exit!, чтобы избежать вызова Kernel#at_exit.

Чтобы избежать появления зомби-процессов, родительский процесс должен вызвать один из методов:

  • Process.wait, чтобы получить статусы завершения дочерних процессов.

  • Process.detach, чтобы зарегистрировать отсутствие интереса к их статусу.

Поток, вызывающий fork, — единственный поток в созданном дочернем процессе; fork не копирует другие потоки.

Обратите внимание, что метод fork доступен на одних платформах, но не на других:

Process.respond_to?(:fork) # => true # Would be false on some.

Если он недоступен, вместо fork можно использовать ::spawn.

format
Псевдоним для: sprintf
frozen? → true or false Показать исходный код
# File kernel.rb, line 67
def frozen?
  Primitive.attr! :leaf
  Primitive.cexpr! 'rb_obj_frozen_p(self)'
end

Возвращает состояние заморозки объекта obj.

a = [ "a", "b", "c" ]
a.freeze    #=> ["a", "b", "c"]
a.frozen?   #=> true
gets(sep=$/ [, getline_args]) → string or nil Показать исходный код
gets(limit [, getline_args]) → string or nil
gets(sep, limit [, getline_args]) → string or nil
static VALUE
rb_f_gets(int argc, VALUE *argv, VALUE recv)
{
    if (recv == argf) {
        return argf_gets(argc, argv, argf);
    }
    return forward(argf, idGets, argc, argv);
}

Возвращает (и присваивает $_) следующую строку из списка файлов в ARGV (или $*) либо из стандартного ввода, если в командной строке не указаны файлы. В конце файла возвращает nil. Необязательный аргумент задаёт разделитель записей. Разделитель включается в содержимое каждой записи. Разделитель nil считывает всё содержимое целиком, а разделитель нулевой длины считывает ввод абзац за абзацем, где абзацы разделяются двумя последовательными символами новой строки. Если первый аргумент — целое число или задан необязательный второй аргумент, возвращаемая строка не будет длиннее указанного значения в байтах. Если в ARGV указано несколько имён файлов, gets(nil) будет считывать содержимое файлов по очереди.

ARGV << "testfile"
print while gets

выводит:

This is line one
This is line two
This is line three
And so on...

Стиль программирования, при котором $_ используется как неявный параметр, постепенно теряет популярность в сообществе Ruby.

global_variables → array Показать исходный код
static VALUE
f_global_variables(VALUE _)
{
    return rb_f_global_variables();
}

Возвращает массив имён глобальных переменных. Он включает специальные глобальные переменные регулярных выражений, такие как $~ и $+, но не включает нумерованные глобальные переменные регулярных выражений ($1, $2 и т. д.).

global_variables.grep /std/   #=> [:$stdin, :$stdout, :$stderr]
gsub(pattern, replacement) → $_ Показать исходный код
gsub(pattern) {|...| block } → $_
static VALUE
rb_f_gsub(int argc, VALUE *argv, VALUE _)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
    rb_lastline_set(str);
    return str;
}

Эквивалентен $_.gsub..., за исключением того, что $_ обновляется, если выполняется подстановка. Доступен только при указании параметра командной строки -p/-n.

iterator? → true or false Показать исходный код
static VALUE
rb_f_iterator_p(VALUE self)
{
    rb_warn_deprecated("iterator?", "block_given?");
    return rb_f_block_given_p(self);
}

Устарел. Вместо него используйте block_given?.

lambda { |...| block } → a_proc Показать исходный код
static VALUE
f_lambda(VALUE _)
{
    f_lambda_filter_non_literal();
    return rb_block_lambda();
}

Эквивалентен Proc.new, за исключением того, что результирующие объекты Proc проверяют количество переданных при вызове параметров.

load(filename, wrap=false) → true Показать исходный код
static VALUE
rb_f_load(int argc, VALUE *argv, VALUE _)
{
    VALUE fname, wrap;
    rb_scan_args(argc, argv, "11", &fname, &wrap);
    return load_entrypoint_internal(fname, wrap);
}

Загружает и выполняет программу Ruby из файла filename.

Если имя файла — абсолютный путь (например, начинается с «/»), файл будет загружен напрямую по абсолютному пути.

Если имя файла — явный относительный путь (например, начинается с «./» или «../»), файл будет загружен по относительному пути от текущего каталога.

В противном случае файл будет искаться в каталогах библиотек, перечисленных в $LOAD_PATH ($:). Если файл найден в каталоге, будет предпринята попытка загрузить его относительно этого каталога. Если файл не найден ни в одном из каталогов в $LOAD_PATH, он будет загружен по относительному пути от текущего каталога.

Если при попытке загрузки файла он не существует, будет возбуждено исключение LoadError.

Если необязательный параметр wrap равен true, загруженный скрипт будет выполнен в анонимном модуле. Если необязательный параметр wrap является модулем, загруженный скрипт будет выполнен в указанном модуле. Ни при каких обстоятельствах локальные переменные загруженного файла не передаются в среду, из которой выполняется загрузка.

local_variables → array Показать исходный код
static VALUE
rb_f_local_variables(VALUE _)
{
    struct local_var_list vars;
    rb_execution_context_t *ec = GET_EC();
    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
    unsigned int i;

    local_var_list_init(&vars);
    while (cfp) {
        if (cfp->iseq) {
            for (i = 0; i < ISEQ_BODY(cfp->iseq)->local_table_size; i++) {
                local_var_list_add(&vars, ISEQ_BODY(cfp->iseq)->local_table[i]);
            }
        }
        if (!VM_ENV_LOCAL_P(cfp->ep)) {
            /* block */
            const VALUE *ep = VM_CF_PREV_EP(cfp);

            if (vm_collect_local_variables_in_heap(ep, &vars)) {
                break;
            }
            else {
                while (cfp->ep != ep) {
                    cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
                }
            }
        }
        else {
            break;
        }
    }
    return local_var_list_finish(&vars);
}

Возвращает имена текущих локальных переменных.

fred = 1
for i in 1..10
   # ...
end
local_variables   #=> [:fred, :i]
loop { block } Показать исходный код
loop → an_enumerator
# File kernel.rb, line 161
def loop
  Primitive.attr! :inline_block
  unless defined?(yield)
    return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size)'
  end

  begin
    while true
      yield
    end
  rescue StopIteration => e
    e.result
  end
end

Многократно выполняет блок.

Если блок не указан, вместо него возвращается перечислитель.

loop do
  print "Input: "
  line = gets
  # break if q, Q is entered or EOF signal (Ctrl-D on Unix, Ctrl-Z on windows) is sent
  break if !line or line =~ /^q/i
  # ...
end

Исключение StopIteration, возбужденное в блоке, прерывает цикл. В этом случае loop возвращает значение «result», сохранённое в исключении.

enum = Enumerator.new { |y|
  y << "one"
  y << "two"
  :ok
}

result = loop {
  puts enum.next
} #=> :ok
open(path, mode = 'r', perm = 0666, **opts) → io or nil Показать исходный код
open(path, mode = 'r', perm = 0666, **opts) {|io| ... } → obj
static VALUE
rb_f_open(int argc, VALUE *argv, VALUE _)
{
    ID to_open = 0;
    int redirect = FALSE;

    if (argc >= 1) {
        CONST_ID(to_open, "to_open");
        if (rb_respond_to(argv[0], to_open)) {
            redirect = TRUE;
        }
        else {
            VALUE tmp = argv[0];
            FilePathValue(tmp);
            if (NIL_P(tmp)) {
                redirect = TRUE;
            }
            else {
                argv[0] = tmp;
            }
        }
    }
    if (redirect) {
        VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);

        if (rb_block_given_p()) {
            return rb_ensure(rb_yield, io, io_close, io);
        }
        return io;
    }
    return rb_io_s_open(argc, argv, rb_cFile);
}

Создаёт объект IO, связанный с указанным файлом.

Если блок не передан, возвращается файловый поток:

open('t.txt') # => #<File:t.txt>

Если блок передан, он вызывается с открытым файловым потоком, после чего поток закрывается:

open('t.txt') {|f| p f } # => #<File:t.txt (closed)>

Вывод:

#<File:t.txt>

Подробности см. в File.open.

p(object) → obj Показать исходный код
p(*objects) → array of objects
p → nil
static VALUE
rb_f_p(int argc, VALUE *argv, VALUE self)
{
    int i;
    for (i=0; i<argc; i++) {
        VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
        rb_uninterruptible(rb_p_write, inspected);
    }
    return rb_p_result(argc, argv);
}

Для каждого объекта obj выполняет:

$stdout.write(obj.inspect, "\n")

Если передан один объект, возвращает этот объект; если передано несколько объектов, возвращает массив, содержащий эти объекты; если объект не передан, возвращает nil.

Примеры:

r = Range.new(0, 4)
p r                 # => 0..4
p [r, r, r]         # => [0..4, 0..4, 0..4]
p                   # => nil

Вывод:

0..4
[0..4, 0..4, 0..4]

Kernel#p предназначен для отладки. Реализации Ruby могут определять Kernel#p как полностью или частично непрерываемый метод. В CRuby запись данных методом Kernel#p непрерываема.

pretty_inspect () Показать исходный код
# File lib/pp.rb, line 724
def pretty_inspect
  PP.pp(self, ''.dup)
end

Возвращает объект в виде строки с форматированием для удобного чтения.

Дополнительную информацию см. в модуле PP.

print(*objects) → nil Показать исходный код
static VALUE
rb_f_print(int argc, const VALUE *argv, VALUE _)
{
    rb_io_print(argc, argv, rb_ractor_stdout());
    return Qnil;
}

Эквивалентен $stdout.print(*objects); этот метод — простой способ записи в $stdout.

Записывает указанные объекты в $stdout; возвращает nil. Добавляет разделитель выходных записей $OUTPUT_RECORD_SEPARATOR $\), если он не равен nil.

Если задан аргумент objects, для каждого объекта выполняется следующее:

  • Если объект не является строкой, преобразует его с помощью метода to_s.

  • Записывает его в stdout.

  • Если это не последний объект, записывает разделитель выходных полей $OUTPUT_FIELD_SEPARATOR ($,, если он не равен nil.

С разделителями по умолчанию:

objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
$OUTPUT_RECORD_SEPARATOR
$OUTPUT_FIELD_SEPARATOR
print(*objects)

Вывод:

nil
nil
00.00/10+0izerozero

С указанными разделителями:

$OUTPUT_RECORD_SEPARATOR = "\n"
$OUTPUT_FIELD_SEPARATOR = ','
print(*objects)

Вывод:

0,0.0,0/1,0+0i,zero,zero

Если аргументы не заданы, записывает содержимое $_ (обычно это последние пользовательские данные, введённые с клавиатуры):

gets  # Sets $_ to the most recent user input.
print # Prints $_.
printf(format_string, *objects) → nil Показать исходный код
printf(io, format_string, *objects) → nil
static VALUE
rb_f_printf(int argc, VALUE *argv, VALUE _)
{
    VALUE out;

    if (argc == 0) return Qnil;
    if (RB_TYPE_P(argv[0], T_STRING)) {
        out = rb_ractor_stdout();
    }
    else {
        out = argv[0];
        argv++;
        argc--;
    }
    rb_io_write(out, rb_f_sprintf(argc, argv));

    return Qnil;
}

Эквивалентен:

io.write(sprintf(format_string, *objects))

Подробную информацию о format_string см. в разделе Спецификации формата.

Если передан единственный аргумент format_string, форматирует objects в строку, а затем записывает отформатированную строку в $stdout:

printf('%4.4d %10s %2.2f', 24, 24, 24.0)

Вывод (в $stdout):

0024         24 24.00#

Если переданы аргументы io и format_string, форматирует objects в строку, а затем записывает отформатированную строку в io:

printf($stderr, '%4.4d %10s %2.2f', 24, 24, 24.0)

Вывод (в $stderr):

0024         24 24.00# => nil

Если аргументы не заданы, ничего не делает.

proc { |...| block } → a_proc Показать исходный код
static VALUE
f_proc(VALUE _)
{
    return proc_new(rb_cProc, FALSE);
}

Эквивалентен Proc.new.

putc(int) → int Показать исходный код
static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
    VALUE r_stdout = rb_ractor_stdout();
    if (recv == r_stdout) {
        return rb_io_putc(recv, ch);
    }
    return forward(r_stdout, rb_intern("putc"), 1, &ch);
}

Эквивалентен:

$stdout.putc(int)

Важную информацию о многобайтовых символах см. в IO#putc.

puts(*objects) → nil Показать исходный код
static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
    VALUE r_stdout = rb_ractor_stdout();
    if (recv == r_stdout) {
        return rb_io_puts(argc, argv, recv);
    }
    return forward(r_stdout, rb_intern("puts"), argc, argv);
}

Эквивалентен

$stdout.puts(objects)
raise(exception, message = exception.to_s, backtrace = nil, cause: $!) Показать исходный код
raise(message = nil, cause: $!)
static VALUE
f_raise(int c, VALUE *v, VALUE _)
{
    return rb_f_raise(c, v);
}

Возбуждает исключение; см. раздел Исключения.

Аргумент exception задаёт класс нового исключения; это должен быть класс Exception или один из его подклассов (чаще всего RuntimeError или StandardError) либо экземпляр одного из этих классов:

begin
  raise(StandardError)
rescue => x
  p x.class
end
# => StandardError

Аргумент message задаёт сохранённое сообщение нового исключения, которое можно получить методом Exception#message; сообщение должно быть объектом, преобразуемым в строку, или nil:

begin
  raise(StandardError, 'Boom')
rescue => x
  p x.message
end
# => "Boom"

Если аргумент message не задан, сообщением становится имя класса исключения.

См. раздел Сообщения.

Аргумент backtrace можно использовать для изменения трассировки стека нового исключения, возвращаемой методами Exception#backtrace и Exception#backtrace_locations; трассировка стека должна быть массивом объектов Thread::Backtrace::Location, массивом строк, одной строкой или nil.

Наиболее последовательный вариант — использовать массив экземпляров Thread::Backtrace::Location; при возможности следует отдавать предпочтение ему. Необходимое значение можно получить с помощью caller_locations или скопировать из Exception#backtrace_locations другого исключения:

begin
  do_some_work()
rescue ZeroDivisionError => ex
  raise(LogicalError, "You have an error in your math", ex.backtrace_locations)
end

Оба метода — Exception#backtrace и Exception#backtrace_locations — у возбужденного исключения получают одну и ту же трассировку стека.

Если нужный стек локаций недоступен и его требуется создать с нуля, можно использовать массив строк или одну строку. В этом случае задаётся только Exception#backtrace:

begin
  raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1])
rescue => ex
  p ex.backtrace
  # => ["dsl.rb:3", "framework.rb:1"]
  p ex.backtrace_locations
  # => nil
end

Если аргумент backtrace не задан, трассировка стека формируется на основе массива объектов Thread::Backtrace::Location, полученного из стека вызовов.

См. раздел Трассировки стека.

Ключевой аргумент cause задаёт сохранённую причину нового исключения, которую можно получить методом Exception#cause; причиной должен быть объект исключения (Exception или один из его подклассов) либо nil:

begin
  raise(StandardError, cause: RuntimeError.new)
rescue => x
  p x.cause
end
# => #<RuntimeError: RuntimeError>

Если ключевой аргумент cause не задан, причиной становится значение $!.

См. раздел Причина.

В альтернативной форме вызова, когда аргумент exception не задан, возбуждается новое исключение класса, указанного в $!, или класса RuntimeError, если $! равно nil:

begin
  raise
rescue => x
  p x
end
# => RuntimeError

Если аргумент exception не задан, можно указать аргумент message и ключевой аргумент cause, но нельзя указать аргумент backtrace.

cause нельзя указывать как единственный аргумент.

Также имеет псевдоним: fail
rand(max=0) → number Показать исходный код
static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
    VALUE vmax;
    rb_random_t *rnd = default_rand_start();

    if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
        VALUE v = rand_range(obj, rnd, vmax);
        if (v != Qfalse) return v;
        vmax = rb_to_int(vmax);
        if (vmax != INT2FIX(0)) {
            v = rand_int(obj, rnd, vmax, 0);
            if (!NIL_P(v)) return v;
        }
    }
    return DBL2NUM(random_real(obj, rnd, TRUE));
}

Если вызвать rand без аргумента или если max.to_i.abs == 0, метод возвращает псевдослучайное число с плавающей точкой от 0.0 включительно до 1.0 не включительно.

rand        #=> 0.2725926052826416

Если max.abs больше или равно 1, rand возвращает псевдослучайное целое число, большее или равное 0 и меньшее max.to_i.abs.

rand(100)   #=> 12

Если max — это Range, rand возвращает случайное число, для которого выполняется условие range.member?(number) == true.

Для max допустимы отрицательные значения и числа с плавающей точкой, но результат может оказаться неожиданным.

rand(-100) # => 87
rand(-0.5) # => 0.8130921818028143
rand(1.9)  # equivalent to rand(1), which is always 0

Метод Kernel.srand позволяет обеспечить воспроизводимость последовательностей случайных чисел при разных запусках программы.

Связанный метод: Random.rand.

rand(100.0)        # => 64 (Integer because max.to_i is 100)
Random.rand(100.0) # => 30.315320967824523
readline(sep = $/, chomp: false) → string Показать исходный код
readline(limit, chomp: false) → string
readline(sep, limit, chomp: false) → string
static VALUE
rb_f_readline(int argc, VALUE *argv, VALUE recv)
{
    if (recv == argf) {
        return argf_readline(argc, argv, argf);
    }
    return forward(argf, rb_intern("readline"), argc, argv);
}

Эквивалентен методу Kernel#gets, за исключением того, что при вызове в конце потока возбуждает исключение:

$ cat t.txt | ruby -e "p readlines; readline"
["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
in `readline': end of file reached (EOFError)

Необязательный ключевой аргумент chomp указывает, следует ли исключать разделители строк.

readlines(sep = $/, chomp: false, **enc_opts) → array Показать исходный код
readlines(limit, chomp: false, **enc_opts) → array
readlines(sep, limit, chomp: false, **enc_opts) → array
static VALUE
rb_f_readlines(int argc, VALUE *argv, VALUE recv)
{
    if (recv == argf) {
        return argf_readlines(argc, argv, argf);
    }
    return forward(argf, rb_intern("readlines"), argc, argv);
}

Возвращает массив, содержащий строки, полученные последовательными вызовами Kernel#gets до конца потока (см. Построчный ввод-вывод).

Если задан только строковый аргумент sep, возвращает оставшиеся строки, определяемые разделителем строк sep, или nil, если разделитель не задан; см. раздел Разделитель строк:

# Default separator.
$ cat t.txt | ruby -e "p readlines"
["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]

# Specified separator.
$ cat t.txt | ruby -e "p readlines 'li'"
["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]

# Get-all separator.
$ cat t.txt | ruby -e "p readlines nil"
["First line\nSecond line\n\nFourth line\nFifth line\n"]

# Get-paragraph separator.
$ cat t.txt | ruby -e "p readlines ''"
["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]

Если задан только целочисленный аргумент limit, ограничивает количество байтов в строке; см. раздел Ограничение длины строки:

$cat t.txt | ruby -e "p readlines 10"
["First line", "\n", "Second lin", "e\n", "\n", "Fourth lin", "e\n", "Fifth line", "\n"]

$cat t.txt | ruby -e "p readlines 11"
["First line\n", "Second line", "\n", "\n", "Fourth line", "\n", "Fifth line\n"]

$cat t.txt | ruby -e "p readlines 12"
["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]

Если заданы аргументы sep и limit, объединяются оба способа поведения (см. раздел Разделитель строк и ограничение длины строки).

Необязательный ключевой аргумент chomp указывает, следует ли исключать разделители строк:

$ cat t.txt | ruby -e "p readlines(chomp: true)"
["First line", "Second line", "", "Fourth line", "Fifth line"]

Необязательные ключевые аргументы enc_opts задают параметры кодировки; см. раздел Параметры кодировки.

require_relative(string) → true or false Показать исходный код
VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
    return rb_require_relative_entrypoint(fname);
}

Ruby пытается загрузить библиотеку с именем string относительно каталога, содержащего файл, в котором выполняется require. Если файл не существует, возбуждается исключение LoadError. Возвращает true, если файл был загружен, и false, если файл уже был загружен ранее.

select(read_ios, write_ios = [], error_ios = [], timeout = nil) → array or nil Показать исходный код
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
    VALUE scheduler = rb_fiber_scheduler_current();
    if (scheduler != Qnil) {
        // It's optionally supported.
        VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);
        if (!UNDEF_P(result)) return result;
    }

    VALUE timeout;
    struct select_args args;
    struct timeval timerec;
    int i;

    rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
    if (NIL_P(timeout) || is_pos_inf(timeout)) {
        args.timeout = 0;
    }
    else {
        timerec = rb_time_interval(timeout);
        args.timeout = &timerec;
    }

    for (i = 0; i < numberof(args.fdsets); ++i)
        rb_fd_init(&args.fdsets[i]);

    return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}

Вызывает системный вызов select(2), который отслеживает несколько файловых дескрипторов и ожидает, пока один или несколько из них не будут готовы к выполнению определённого типа операции ввода-вывода.

Реализован не на всех платформах.

Каждый из аргументов read_ios, write_ios и error_ios представляет собой массив объектов IO.

Аргумент timeout — это числовой интервал ожидания в секундах (например, целое число или число с плавающей точкой). timeout также может быть nil или Float::INFINITY. nil и Float::INFINITY означают отсутствие тайм-аута.

Метод отслеживает объекты IO, переданные во все три массива, и ожидает готовности некоторых из них; возвращает массив из 3 элементов:

  • Массив объектов из read_ios, готовых к чтению.

  • Массив объектов из write_ios, готовых к записи.

  • Массив объектов из error_ios, для которых имеются ожидающие исключения.

Если ни один объект не станет готовым в течение заданного timeout, возвращается nil.

IO.select проверяет буфер объектов IO на наличие данных, чтобы определить возможность чтения. Если буфер IO не пуст, IO.select немедленно сообщает о готовности к чтению. Такая «проверка» выполняется только для объектов IO. Для объектов, подобных IO, например OpenSSL::SSL::SSLSocket, она не выполняется.

Лучше всего вызывать IO.select после неблокирующих методов, таких как read_nonblock, write_nonblock и т. д. Эти методы вызывают исключение, к которому добавлен модуль IO::WaitReadable или IO::WaitWritable. Модули сообщают вызывающему коду, как следует ожидать с помощью IO.select. Если возникает исключение IO::WaitReadable, вызывающий код должен ожидать готовности к чтению. Если возникает исключение IO::WaitWritable, вызывающий код должен ожидать готовности к записи.

Таким образом, блокирующее чтение (readpartial) можно эмулировать с помощью read_nonblock и IO.select следующим образом:

begin
  result = io_like.read_nonblock(maxlen)
rescue IO::WaitReadable
  IO.select([io_like])
  retry
rescue IO::WaitWritable
  IO.select(nil, [io_like])
  retry
end

В частности, сочетание неблокирующих методов и IO.select предпочтительно для объектов, подобных IO, например OpenSSL::SSL::SSLSocket. У них есть метод to_io, возвращающий базовый объект IO. IO.select вызывает to_io, чтобы получить файловый дескриптор для ожидания.

Это означает, что уведомление IO.select о готовности к чтению не означает готовность к чтению из объекта OpenSSL::SSL::SSLSocket.

Наиболее вероятная ситуация состоит в том, что OpenSSL::SSL::SSLSocket буферизует данные. IO.select не видит этот буфер. Поэтому IO.select может блокироваться, даже если OpenSSL::SSL::SSLSocket#readpartial не блокируется.

Однако возможны и другие, более сложные ситуации.

SSL — это протокол, состоящий из последовательности записей. Запись состоит из нескольких байтов. Поэтому, если удалённая сторона SSL отправляет неполную запись, IO.select сообщает о готовности к чтению, но OpenSSL::SSL::SSLSocket не может расшифровать ни одного байта, и OpenSSL::SSL::SSLSocket#readpartial блокируется.

Кроме того, удалённая сторона может запросить повторное согласование SSL, из-за которого локальному механизму SSL придётся записать некоторые данные. Это означает, что OpenSSL::SSL::SSLSocket#readpartial может вызвать системный вызов записи, который может блокироваться. В такой ситуации OpenSSL::SSL::SSLSocket#read_nonblock вызывает исключение IO::WaitWritable, а не блокируется. Поэтому вызывающий код, как и в примере выше, должен ожидать готовности к записи.

Сочетание неблокирующих методов и IO.select также полезно для потоков, например tty, каналов и сокетов, когда из одного потока читают несколько процессов.

Наконец, разработчики ядра Linux не гарантируют, что уведомление о готовности к чтению от select(2) означает готовность к чтению при последующем вызове read(2), даже если процесс всего один; см. select(2)

Вызов IO.select перед IO#readpartial обычно работает хорошо. Однако это не лучший способ использования IO.select.

Уведомление select(2) о готовности к записи не показывает, сколько байтов можно записать. Метод IO#write блокируется, пока не будет записана вся переданная строка. Поэтому IO#write(two or more bytes) может заблокироваться после уведомления IO.select о готовности к записи. Чтобы избежать блокировки, необходимо использовать IO#write_nonblock.

Блокирующую запись (write) можно эмулировать с помощью write_nonblock и IO.select следующим образом: при повторном согласовании SSL в OpenSSL::SSL::SSLSocket также следует перехватывать IO::WaitReadable.

while 0 < string.bytesize
  begin
    written = io_like.write_nonblock(string)
  rescue IO::WaitReadable
    IO.select([io_like])
    retry
  rescue IO::WaitWritable
    IO.select(nil, [io_like])
    retry
  end
  string = string.byteslice(written..-1)
end

Пример:

rp, wp = IO.pipe
mesg = "ping "
100.times {
  # IO.select follows IO#read.  Not the best way to use IO.select.
  rs, ws, = IO.select([rp], [wp])
  if r = rs[0]
    ret = r.read(5)
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
    end
  end
  if w = ws[0]
    w.write(mesg)
  end
}

Вывод:

ping pong
ping pong
ping pong
(snipped)
ping
set_trace_func(proc) → proc Показать исходный код
set_trace_func(nil) → nil
static VALUE
set_trace_func(VALUE obj, VALUE trace)
{
    rb_remove_event_hook(call_trace_func);

    if (NIL_P(trace)) {
        return Qnil;
    }

    if (!rb_obj_is_proc(trace)) {
        rb_raise(rb_eTypeError, "trace_func needs to be Proc");
    }

    rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
    return trace;
}

Назначает proc обработчиком трассировки или отключает трассировку, если параметр равен nil.

Примечание: этот метод устарел; вместо него используйте TracePoint.

proc принимает до шести параметров:

  • строку с именем события

  • строку с именем файла

  • номер строки

  • символ с именем метода или nil

  • binding или nil

  • класс, модуль или nil

proc вызывается при каждом возникновении события.

События:

"c-call"

вызов подпрограммы на языке C

"c-return"

возврат из подпрограммы на языке C

"call"

вызов метода Ruby

"class"

начало определения класса или модуля

"end"

завершение определения класса или модуля

"line"

выполнение кода на новой строке

"raise"

генерация исключения

"return"

возврат из метода Ruby

В контексте proc трассировка отключена.

class Test
  def test
    a = 1
    b = 2
  end
end

set_trace_func proc { |event, file, line, id, binding, class_or_module|
  printf "%8s %s:%-2d %16p %14p\n", event, file, line, id, class_or_module
}
t = Test.new
t.test

Выводит:

c-return prog.rb:8   :set_trace_func         Kernel
    line prog.rb:11              nil            nil
  c-call prog.rb:11             :new          Class
  c-call prog.rb:11      :initialize    BasicObject
c-return prog.rb:11      :initialize    BasicObject
c-return prog.rb:11             :new          Class
    line prog.rb:12              nil            nil
    call prog.rb:2             :test           Test
    line prog.rb:3             :test           Test
    line prog.rb:4             :test           Test
  return prog.rb:5             :test           Test
sleep(secs = nil) → slept_secs Показать исходный код
static VALUE
rb_f_sleep(int argc, VALUE *argv, VALUE _)
{
    time_t beg = time(0);
    VALUE scheduler = rb_fiber_scheduler_current();

    if (scheduler != Qnil) {
        rb_fiber_scheduler_kernel_sleepv(scheduler, argc, argv);
    }
    else {
        if (argc == 0 || (argc == 1 && NIL_P(argv[0]))) {
            rb_thread_sleep_forever();
        }
        else {
            rb_check_arity(argc, 0, 1);
            rb_thread_wait_for(rb_time_interval(argv[0]));
        }
    }

    time_t end = time(0) - beg;

    return TIMET2NUM(end);
}

Приостанавливает выполнение текущего потока на количество секунд, указанное числовым аргументом secs, или навсегда, если secs равен nil; возвращает целое число секунд приостановки (округлённое).

Time.new  # => 2008-03-08 19:56:19 +0900
sleep 1.2 # => 1
Time.new  # => 2008-03-08 19:56:20 +0900
sleep 1.9 # => 2
Time.new  # => 2008-03-08 19:56:22 +0900
spawn([env, ] command_line, options = {}) → pid Показать исходный код
spawn([env, ] exe_path, *args, options = {}) → pid
static VALUE
rb_f_spawn(int argc, VALUE *argv, VALUE _)
{
    rb_pid_t pid;
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;

    execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
    eargp = rb_execarg_get(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

    pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));

    if (pid == -1) {
        int err = errno;
        rb_exec_fail(eargp, err, errmsg);
        RB_GC_GUARD(execarg_obj);
        rb_syserr_fail_str(err, fail_str);
    }
#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
    return PIDT2NUM(pid);
#else
    return Qnil;
#endif
}

Создаёт новый дочерний процесс, выполняя в нём одно из следующих действий:

  • Передаёт строку command_line командной оболочке.

  • Запускает исполняемый файл по пути exe_path.

При вызове с недоверенными данными этот метод может быть уязвим с точки зрения безопасности; см. раздел Инъекция команд.

Возвращает идентификатор процесса (pid) нового процесса, не дожидаясь его завершения.

Чтобы избежать появления процессов-зомби, родительский процесс должен вызвать один из следующих методов:

  • Process.wait — для сбора кодов завершения дочерних процессов.

  • Process.detach — чтобы отказаться от отслеживания их состояния.

Новый процесс создаётся с помощью системного вызова exec; он может унаследовать часть окружения вызывающей программы (возможно, включая открытые файловые дескрипторы).

Аргумент env, если он задан, представляет собой хеш, влияющий на ENV нового процесса; см. раздел Окружение выполнения.

Аргумент options — это хеш параметров нового процесса; см. раздел Параметры выполнения.

Первый обязательный аргумент должен быть одним из следующих:

  • command_line, если это строка, начинающаяся с зарезервированного слова или специальной встроенной команды оболочки либо содержащая один или несколько метасимволов.

  • exe_path в противном случае.

Аргумент command_line

Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова или специальной встроенной команды оболочки либо содержать метасимволы:

spawn('if true; then echo "Foo"; fi') # => 798847 # Shell reserved word.
Process.wait                          # => 798847
spawn('exit')                         # => 798848 # Built-in.
Process.wait                          # => 798848
spawn('date > /tmp/date.tmp')         # => 798879 # Contains meta character.
Process.wait                          # => 798849
spawn('date > /nop/date.tmp')         # => 798882 # Issues error message.
Process.wait                          # => 798882

Командная строка также может содержать аргументы и параметры команды:

spawn('echo "Foo"') # => 799031
Process.wait        # => 799031

Вывод:

Foo

Подробности об оболочке см. в разделе Оболочка выполнения.

Вызывает исключение, если новый процесс не удалось запустить.

Аргумент exe_path

Аргумент exe_path — это один из следующих вариантов:

  • Строка с путём к вызываемому исполняемому файлу.

  • Массив из двух элементов, содержащий путь к вызываемому исполняемому файлу и строку, которая будет использоваться в качестве имени запускаемого процесса.

    spawn('/usr/bin/date') # Path to date on Unix-style system.
    Process.wait
    

    Вывод:

    Mon Aug 28 11:43:10 AM CDT 2023

Ruby запускает исполняемый файл напрямую. Эта форма не использует оболочку; ограничения см. в разделе Аргументы args.

Если задан один или несколько аргументов args, каждый из них передаётся исполняемому файлу как аргумент или параметр:

spawn('echo', 'C*')             # => 799392
Process.wait                    # => 799392
spawn('echo', 'hello', 'world') # => 799393
Process.wait                    # => 799393

Вывод:

C*
hello world

Вызывает исключение, если новый процесс не удалось запустить.

sprintf(format_string *objects) → string Показать исходный код
static VALUE
f_sprintf(int c, const VALUE *v, VALUE _)
{
    return rb_f_sprintf(c, v);
}

Возвращает строку, полученную в результате форматирования objects в format_string.

Подробнее о format_string см. в разделе Спецификации формата.

Также имеет псевдоним: format
srand(number = Random.new_seed) → old_seed Показать исходный код
static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
    VALUE seed, old;
    rb_random_mt_t *r = default_mt();

    if (rb_check_arity(argc, 0, 1) == 0) {
        seed = random_seed(obj);
    }
    else {
        seed = rb_to_int(argv[0]);
    }
    old = r->base.seed;
    rand_init(&random_mt_if, &r->base, seed);
    r->base.seed = seed;

    return old;
}

Инициализирует системный генератор псевдослучайных чисел значением number. Возвращает предыдущее значение начального числа.

Если number не указан, генератор инициализируется с использованием источника энтропии, предоставляемого операционной системой, если он доступен (/dev/urandom в Unix-системах или криптографический поставщик RSA в Windows); затем это значение комбинируется со временем, идентификатором процесса и порядковым номером.

srand можно использовать, чтобы обеспечить повторяемые последовательности псевдослучайных чисел при разных запусках программы. Если задать известное начальное число, поведение программы во время тестирования станет детерминированным.

srand 1234               # => 268519324636777531569100071560086917274
[ rand, rand ]           # => [0.1915194503788923, 0.6221087710398319]
[ rand(10), rand(1000) ] # => [4, 664]
srand 1234               # => 1234
[ rand, rand ]           # => [0.1915194503788923, 0.6221087710398319]
sub(pattern, replacement) → $_ Показать исходный код
sub(pattern) {|...| block } → $_
static VALUE
rb_f_sub(int argc, VALUE *argv, VALUE _)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
    rb_lastline_set(str);
    return str;
}

Аналогичен $_.sub(args), за исключением того, что $_ обновляется, если замена выполнена. Доступен только при указании параметра командной строки -p/-n.

syscall(integer_callno, *arguments) → integer Показать исходный код
static VALUE
rb_f_syscall(int argc, VALUE *argv, VALUE _)
{
    VALUE arg[8];
#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
# define SYSCALL __syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
# if SIZEOF_LONG == 8
    long num, retval = -1;
# elif SIZEOF_LONG_LONG == 8
    long long num, retval = -1;
# else
#  error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
# endif
#elif defined(__linux__)
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
    /*
     * Linux man page says, syscall(2) function prototype is below.
     *
     *     int syscall(int number, ...);
     *
     * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
     */
    long num, retval = -1;
#else
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2INT(x)
# define RETVAL2NUM(x) INT2NUM(x)
    int num, retval = -1;
#endif
    int i;

    if (RTEST(ruby_verbose)) {
        rb_category_warning(RB_WARN_CATEGORY_DEPRECATED,
            "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
    }

    if (argc == 0)
        rb_raise(rb_eArgError, "too few arguments for syscall");
    if (argc > numberof(arg))
        rb_raise(rb_eArgError, "too many arguments for syscall");
    num = NUM2SYSCALLID(argv[0]); ++argv;
    for (i = argc - 1; i--; ) {
        VALUE v = rb_check_string_type(argv[i]);

        if (!NIL_P(v)) {
            StringValue(v);
            rb_str_modify(v);
            arg[i] = (VALUE)StringValueCStr(v);
        }
        else {
            arg[i] = (VALUE)NUM2LONG(argv[i]);
        }
    }

    switch (argc) {
      case 1:
        retval = SYSCALL(num);
        break;
      case 2:
        retval = SYSCALL(num, arg[0]);
        break;
      case 3:
        retval = SYSCALL(num, arg[0],arg[1]);
        break;
      case 4:
        retval = SYSCALL(num, arg[0],arg[1],arg[2]);
        break;
      case 5:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
        break;
      case 6:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
        break;
      case 7:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
        break;
      case 8:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
        break;
    }

    if (retval == -1)
        rb_sys_fail(0);
    return RETVAL2NUM(retval);
#undef SYSCALL
#undef NUM2SYSCALLID
#undef RETVAL2NUM
}

Вызывает системный вызов Posix syscall(2), который вызывает указанную функцию.

Вызывает функцию операционной системы, определённую аргументом integer_callno; возвращает результат функции или вызывает исключение SystemCallError в случае сбоя. Эффект вызова зависит от платформы. Аргументы и возвращаемое значение зависят от платформы.

Для каждого аргумента arguments: если это целое число, оно передаётся напрямую; если строка, она интерпретируется как двоичная последовательность байтов. Таких аргументов может быть до девяти.

Аргументы integer_callno и argument, а также возвращаемое значение зависят от платформы.

Примечание: метод syscall по сути небезопасен и непереносим. Для более безопасного и немного более переносимого программирования предпочтительна библиотека DL (Fiddle).

Реализован не на всех платформах.

system([env, ] command_line, options = {}, exception: false) → true, false, or nil Показать исходный код
system([env, ] exe_path, *args, options = {}, exception: false) → true, false, or nil
static VALUE
rb_f_system(int argc, VALUE *argv, VALUE _)
{
    rb_thread_t *th = GET_THREAD();
    VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
    struct rb_execarg *eargp = rb_execarg_get(execarg_obj);

    struct rb_process_status status = {0};
    eargp->status = &status;

    last_status_clear(th);

    // This function can set the thread's last status.
    // May be different from waitpid_state.pid on exec failure.
    rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0);

    if (pid > 0) {
        VALUE status = rb_process_status_wait(pid, 0);
        struct rb_process_status *data = rb_check_typeddata(status, &rb_process_status_type);
        // Set the last status:
        rb_obj_freeze(status);
        th->last_status = status;

        if (data->status == EXIT_SUCCESS) {
            return Qtrue;
        }

        if (data->error != 0) {
            if (eargp->exception) {
                VALUE command = eargp->invoke.sh.shell_script;
                RB_GC_GUARD(execarg_obj);
                rb_syserr_fail_str(data->error, command);
            }
            else {
                return Qnil;
            }
        }
        else if (eargp->exception) {
            VALUE command = eargp->invoke.sh.shell_script;
            VALUE str = rb_str_new_cstr("Command failed with");
            rb_str_cat_cstr(pst_message_status(str, data->status), ": ");
            rb_str_append(str, command);
            RB_GC_GUARD(execarg_obj);
            rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str));
        }
        else {
            return Qfalse;
        }

        RB_GC_GUARD(status);
    }

    if (eargp->exception) {
        VALUE command = eargp->invoke.sh.shell_script;
        RB_GC_GUARD(execarg_obj);
        rb_syserr_fail_str(errno, command);
    }
    else {
        return Qnil;
    }
}

Создаёт новый дочерний процесс, выполняя в нём одно из следующих действий:

  • Передаёт строку command_line командной оболочке.

  • Запускает исполняемый файл по пути exe_path.

При вызове с недоверенными данными этот метод может быть уязвим с точки зрения безопасности; см. раздел Инъекция команд.

Возвращает:

  • true, если команда завершилась с нулевым кодом состояния.

  • false, если код завершения — ненулевое целое число.

  • nil, если команду не удалось выполнить.

Вызывает исключение (вместо возврата false или nil), если именованный аргумент exception установлен в true.

Присваивает код ошибки команды переменной $?.

Новый процесс создаётся с помощью системного вызова system; он может унаследовать часть окружения вызывающей программы (возможно, включая открытые файловые дескрипторы).

Аргумент env, если он задан, представляет собой хеш, влияющий на ENV нового процесса; см. раздел Окружение выполнения.

Аргумент options — это хеш параметров нового процесса; см. раздел Параметры выполнения.

Первый обязательный аргумент должен быть одним из следующих:

  • command_line, если это строка, начинающаяся с зарезервированного слова или специальной встроенной команды оболочки либо содержащая один или несколько метасимволов.

  • exe_path в противном случае.

Аргумент command_line

Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова или специальной встроенной команды оболочки либо содержать метасимволы:

system('if true; then echo "Foo"; fi')          # => true  # Shell reserved word.
system('exit')                                  # => true  # Built-in.
system('date > /tmp/date.tmp')                  # => true  # Contains meta character.
system('date > /nop/date.tmp')                  # => false
system('date > /nop/date.tmp', exception: true) # Raises RuntimeError.

Присваивает код ошибки команды переменной $?:

system('exit')                             # => true  # Built-in.
$?                                         # => #<Process::Status: pid 640610 exit 0>
system('date > /nop/date.tmp')             # => false
$?                                         # => #<Process::Status: pid 640742 exit 2>

Командная строка также может содержать аргументы и параметры команды:

system('echo "Foo"') # => true

Вывод:

Foo

Подробности об оболочке см. в разделе Оболочка выполнения.

Вызывает исключение, если новый процесс не удалось запустить.

Аргумент exe_path

Аргумент exe_path — это один из следующих вариантов:

  • Строка с путём к вызываемому исполняемому файлу.

  • Массив из двух элементов, содержащий путь к исполняемому файлу и строку, которая будет использоваться в качестве имени запускаемого процесса.

Пример:

system('/usr/bin/date') # => true # Path to date on Unix-style system.
system('foo')           # => nil  # Command failed.

Вывод:

Mon Aug 28 11:43:10 AM CDT 2023

Присваивает код ошибки команды переменной $?:

system('/usr/bin/date') # => true
$?                      # => #<Process::Status: pid 645605 exit 0>
system('foo')           # => nil
$?                      # => #<Process::Status: pid 645608 exit 127>

Ruby запускает исполняемый файл напрямую. Эта форма не использует оболочку; ограничения см. в разделе Аргументы args.

system('doesnt_exist') # => nil

Если задан один или несколько аргументов args, каждый из них передаётся исполняемому файлу как аргумент или параметр:

system('echo', 'C*')             # => true
system('echo', 'hello', 'world') # => true

Вывод:

C*
hello world

Вызывает исключение, если новый процесс не удалось запустить.

tap {|x| block } → obj Показать исходный код
# File kernel.rb, line 89
def tap
  Primitive.attr! :inline_block
  yield(self)
  self
end

Передаёт self блоку, а затем возвращает self. Основное назначение этого метода — «вклиниться» в цепочку вызовов методов, чтобы выполнить операции над промежуточными результатами цепочки.

(1..10)                  .tap {|x| puts "original: #{x}" }
  .to_a                  .tap {|x| puts "array:    #{x}" }
  .select {|x| x.even? } .tap {|x| puts "evens:    #{x}" }
  .map {|x| x*x }        .tap {|x| puts "squares:  #{x}" }
test(char, path0, path1 = nil) → object Показать исходный код
static VALUE
rb_f_test(int argc, VALUE *argv, VALUE _)
{
    int cmd;

    if (argc == 0) rb_check_arity(argc, 2, 3);
    cmd = NUM2CHR(argv[0]);
    if (cmd == 0) {
        goto unknown;
    }
    if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
        CHECK(1);
        switch (cmd) {
          case 'b':
            return rb_file_blockdev_p(0, argv[1]);

          case 'c':
            return rb_file_chardev_p(0, argv[1]);

          case 'd':
            return rb_file_directory_p(0, argv[1]);

          case 'e':
            return rb_file_exist_p(0, argv[1]);

          case 'f':
            return rb_file_file_p(0, argv[1]);

          case 'g':
            return rb_file_sgid_p(0, argv[1]);

          case 'G':
            return rb_file_grpowned_p(0, argv[1]);

          case 'k':
            return rb_file_sticky_p(0, argv[1]);

          case 'l':
            return rb_file_symlink_p(0, argv[1]);

          case 'o':
            return rb_file_owned_p(0, argv[1]);

          case 'O':
            return rb_file_rowned_p(0, argv[1]);

          case 'p':
            return rb_file_pipe_p(0, argv[1]);

          case 'r':
            return rb_file_readable_p(0, argv[1]);

          case 'R':
            return rb_file_readable_real_p(0, argv[1]);

          case 's':
            return rb_file_size_p(0, argv[1]);

          case 'S':
            return rb_file_socket_p(0, argv[1]);

          case 'u':
            return rb_file_suid_p(0, argv[1]);

          case 'w':
            return rb_file_writable_p(0, argv[1]);

          case 'W':
            return rb_file_writable_real_p(0, argv[1]);

          case 'x':
            return rb_file_executable_p(0, argv[1]);

          case 'X':
            return rb_file_executable_real_p(0, argv[1]);

          case 'z':
            return rb_file_zero_p(0, argv[1]);
        }
    }

    if (strchr("MAC", cmd)) {
        struct stat st;
        VALUE fname = argv[1];

        CHECK(1);
        if (rb_stat(fname, &st) == -1) {
            int e = errno;
            FilePathValue(fname);
            rb_syserr_fail_path(e, fname);
        }

        switch (cmd) {
          case 'A':
            return stat_atime(&st);
          case 'M':
            return stat_mtime(&st);
          case 'C':
            return stat_ctime(&st);
        }
    }

    if (cmd == '-') {
        CHECK(2);
        return rb_file_identical_p(0, argv[1], argv[2]);
    }

    if (strchr("=<>", cmd)) {
        struct stat st1, st2;
        stat_timestamp t1, t2;

        CHECK(2);
        if (rb_stat(argv[1], &st1) < 0) return Qfalse;
        if (rb_stat(argv[2], &st2) < 0) return Qfalse;

        t1 = stat_mtimespec(&st1);
        t2 = stat_mtimespec(&st2);

        switch (cmd) {
          case '=':
            if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
            return Qfalse;

          case '>':
            if (t1.tv_sec > t2.tv_sec) return Qtrue;
            if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
            return Qfalse;

          case '<':
            if (t1.tv_sec < t2.tv_sec) return Qtrue;
            if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
            return Qfalse;
        }
    }
  unknown:
    /* unknown command */
    if (ISPRINT(cmd)) {
        rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
    }
    else {
        rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
    }
    UNREACHABLE_RETURN(Qundef);
}

Выполняет проверку одной или двух сущностей файловой системы по указанным путям path0 и path1:

  • Каждый путь path0 или path1 указывает на файл, каталог, устройство, канал и т. д.

  • Символ char выбирает конкретную проверку.

Проверки:

  • Каждая из этих проверок применяется только к сущности по пути path0 и возвращает true или false; для несуществующей сущности возвращает false (исключение не вызывается):

    Символ Проверка
    'b' Является ли сущность блочным устройством.
    'c' Является ли сущность символьным устройством.
    'd' Является ли сущность каталогом.
    'e' Существует ли сущность.
    'f' Является ли сущность существующим обычным файлом.
    'g' Установлен ли у сущности бит setgid.
    'G' Совпадает ли владелец группы сущности с группой вызывающего кода.
    'k' Установлен ли у сущности липкий бит.
    'l' Является ли сущность символической ссылкой.
    'o' Принадлежит ли сущность эффективному uid вызывающего кода.
    'O' Как 'o', но используется реальный uid (а не эффективный uid).
    'p' Является ли сущность устройством FIFO (именованным каналом).
    'r' Доступна ли сущность для чтения с учётом эффективных uid/gid вызывающего кода.
    'R' Как 'r', но используются реальные uid/gid (а не эффективные uid/gid).
    'S' Является ли сущность сокетом.
    'u' Установлен ли у сущности бит setuid.
    'w' Доступна ли сущность для записи с учётом эффективных uid/gid вызывающего кода.
    'W' Как 'w', но используются реальные uid/gid (а не эффективные uid/gid).
    'x' Доступна ли сущность для выполнения с учётом эффективных uid/gid вызывающего кода.
    'X' Как 'x', но используются реальные uid/gid (а не эффективные uid/gid).
    'z' Существует ли сущность и имеет ли она нулевую длину.
  • Эта проверка применяется только к сущности по пути path0 и возвращает целочисленный размер или nil:

    Символ Проверка
    's' Возвращает положительное целое число, равное размеру, если сущность существует и имеет ненулевую длину; в противном случае возвращает nil.
  • Каждая из этих проверок применяется только к сущности по пути path0 и возвращает объект Time; если сущность не существует, вызывает исключение:

    Символ Проверка
    'A' Время последнего доступа к сущности.
    'C' Время последнего изменения сущности.
    'M' Время последней модификации сущности.
  • Каждая из этих проверок сравнивает время модификации (mtime) сущностей по путям path0 и path1 и возвращает true или false; если хотя бы одна сущность не существует, возвращает false:

    Символ Проверка
    '<' Меньше ли mtime сущности по пути path0, чем у сущности по пути path1.
    '=' Равно ли mtime сущности по пути path0 времени у сущности по пути path1.
    '>' Больше ли mtime сущности по пути path0, чем у сущности по пути path1.
  • Эта проверка сравнивает содержимое сущностей по путям path0 и path1 и возвращает true или false; если хотя бы одна сущность не существует, возвращает false:

    Символ Проверка
    '-' Существуют ли сущности и идентичны ли они.
then {|x| block } → an_object Показать исходный код
# File kernel.rb, line 121
def then
  Primitive.attr! :inline_block
  unless defined?(yield)
    return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
  end
  yield(self)
end

Передаёт self блоку и возвращает результат выполнения блока.

3.next.then {|x| x**x }.to_s             #=> "256"

Метод then удобно использовать для передачи значений в цепочках вызовов методов:

require 'open-uri'
require 'json'

construct_url(arguments)
  .then {|url| URI(url).read }
  .then {|response| JSON.parse(response) }

При вызове без блока метод возвращает Enumerator, который можно использовать, например, для условного прерывания цепочки:

# Meets condition, no-op
1.then.detect(&:odd?)            # => 1
# Does not meet condition, drop value
2.then.detect(&:odd?)            # => nil
Также имеет псевдоним: yield_self
throw(tag [, obj]) Показать исходный код
static VALUE
rb_f_throw(int argc, VALUE *argv, VALUE _)
{
    VALUE tag, value;

    rb_scan_args(argc, argv, "11", &tag, &value);
    rb_throw_obj(tag, value);
    UNREACHABLE_RETURN(Qnil);
}

Передаёт управление в конец активного блока catch, ожидающего tag. Вызывает исключение UncaughtThrowError, если для tag нет блока catch. Необязательный второй параметр задаёт возвращаемое значение блока catch; по умолчанию используется nil. Примеры см. в Kernel::catch.

trace_var(symbol, cmd ) → nil Показать исходный код
trace_var(symbol) {|val| block } → nil
static VALUE
f_trace_var(int c, const VALUE *a, VALUE _)
{
    return rb_f_trace_var(c, a);
}

Управляет трассировкой присваиваний глобальным переменным. Параметр symbol указывает переменную (в виде строкового имени или идентификатора-символа). cmd (которым может быть строка или объект Proc) либо блок выполняется при каждом присваивании переменной. Блок или объект Proc получает новое значение переменной в качестве параметра. См. также untrace_var.

trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
$_ = "hello"
$_ = ' there'

Выводит:

$_ is now 'hello'
$_ is now ' there'
trap(signal, command) → obj Показать исходный код
trap(signal) { ... } → obj
static VALUE
sig_trap(int argc, VALUE *argv, VALUE _)
{
    int sig;
    sighandler_t func;
    VALUE cmd;

    rb_check_arity(argc, 1, 2);

    sig = trap_signm(argv[0]);
    if (reserved_signal_p(sig)) {
        const char *name = signo2signm(sig);
        if (name)
            rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
        else
            rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
    }

    if (argc == 1) {
        cmd = rb_block_proc();
        func = sighandler;
    }
    else {
        cmd = argv[1];
        func = trap_handler(&cmd, sig);
    }

    if (rb_obj_is_proc(cmd) &&
        !rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) {
        cmd = rb_proc_isolate(cmd);
    }

    return trap(sig, func, cmd);
}

Задаёт обработку сигналов. Возвращает предыдущий обработчик для указанного сигнала.

Аргумент signal — это имя сигнала (строка или символ, например SIGALRM или SIGUSR1) либо целочисленный номер сигнала. Если signal — строка или символ, начальные символы SIG можно опустить.

Аргумент command или переданный блок задаёт код, который будет выполнен при возникновении сигнала.

Аргумент command также может быть строкой или символом со следующими специальными значениями:

  • IGNORE, SIG_IGN: сигнал будет проигнорирован.

  • DEFAULT, SIG_DFL: будет вызван обработчик Ruby по умолчанию.

  • EXIT: процесс будет завершён сигналом.

  • SYSTEM_DEFAULT: будет вызван обработчик операционной системы по умолчанию.

Специальное имя сигнала EXIT или номер сигнала ноль будет обработан непосредственно перед завершением программы:

Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD")  { puts "Child died" }
fork && Process.wait

Вывод:

Terminating: 27461
Child died
Terminating: 27460
untrace_var(symbol [, cmd] ) → array or nil Показать исходный код
static VALUE
f_untrace_var(int c, const VALUE *a, VALUE _)
{
    return rb_f_untrace_var(c, a);
}

Удаляет трассировку указанной команды для заданной глобальной переменной и возвращает nil. Если команда не указана, удаляет всю трассировку этой переменной и возвращает массив, содержащий фактически удалённые команды.

warn(*msgs, uplevel: nil, category: nil) → nil Показать исходный код
# File warning.rb, line 52
def warn(*msgs, uplevel: nil, category: nil)
  if Primitive.cexpr!("NIL_P(category)")
    Primitive.rb_warn_m(msgs, uplevel, nil)
  elsif Warning[category = Primitive.cexpr!("rb_to_symbol_type(category)")]
    Primitive.rb_warn_m(msgs, uplevel, category)
  end
end

Если предупреждения отключены (например, с помощью флага -W0), ничего не делает. В противном случае преобразует каждое сообщение в строку, добавляет к строке символ новой строки, если строка не заканчивается на него, и вызывает Warning.warn с этой строкой.

warn("warning 1", "warning 2")

выводит:

warning 1
warning 2

Если передан именованный аргумент uplevel, в начало строки добавляется информация для заданного кадра вызова в том же формате, который использует функция C rb_warn.

# In baz.rb
def foo
  warn("invalid call to foo", uplevel: 1)
end

def bar
  foo
end

bar

выводит:

baz.rb:6: warning: invalid call to foo

Если передан именованный аргумент category, категория передаётся в Warning.warn. Указанная категория должна быть одной из следующих:

:deprecated

Используется для предупреждений об устаревших функциях, которые могут быть удалены в будущем.

:experimental

Используется для экспериментальных функций, которые могут измениться в будущих выпусках.

:performance

Используется для предупреждений об API или шаблонах, негативно влияющих на производительность.

yield_self
Псевдоним для: then

Приватные методы экземпляра

JSON (object, opts = nil) Показать исходный код
# File ext/json/lib/json/common.rb, line 1139
def JSON(object, opts = nil)
  JSON[object, opts]
end

Если object — строка или объект, похожий на строку, разбирает строку и возвращает результат разбора в виде структуры данных Ruby. В противном случае создаёт текст JSON из объекта — структуры данных Ruby — и возвращает его.

Аргумент opts передаётся соответственно в generate/parse. Документацию см. в описаниях generate и parse.

Pathname (path) Показать исходный код
# File pathname_builtin.rb, line 1167
def Pathname(path) # :doc:
  return path if Pathname === path
  Pathname.new(path)
end

Создаёт объект Pathname.

URI (uri) Показать исходный код
# File lib/uri/common.rb, line 911
def URI(uri)
  if uri.is_a?(URI::Generic)
    uri
  elsif uri = String.try_convert(uri)
    URI.parse(uri)
  else
    raise ArgumentError,
      "bad argument (expected URI object or URI string)"
  end
end

Возвращает объект URI, производный от заданного uri, которым может быть строка URI или существующий объект URI:

require 'uri'
# Returns a new URI.
uri = URI('http://github.com/ruby/ruby')
# => #<URI::HTTP http://github.com/ruby/ruby>
# Returns the given URI.
URI(uri)
# => #<URI::HTTP http://github.com/ruby/ruby>

Для использования этого метода необходимо подключить ‘uri’.

gem (gem_name, *requirements) Показать исходный код
# File lib/rubygems/core_ext/kernel_gem.rb, line 35
def gem(gem_name, *requirements) # :doc:
  skip_list = (ENV["GEM_SKIP"] || "").split(/:/)
  raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name

  if gem_name.is_a? Gem::Dependency
    unless Gem::Deprecate.skip
      warn "#{Gem.location_of_caller.join ":"}:Warning: Kernel.gem no longer "\
        "accepts a Gem::Dependency object, please pass the name "\
        "and requirements directly"
    end

    requirements = gem_name.requirement
    gem_name = gem_name.name
  end

  dep = Gem::Dependency.new(gem_name, *requirements)

  loaded = Gem.loaded_specs[gem_name]

  return false if loaded && dep.matches_spec?(loaded)

  spec = dep.to_spec

  if spec
    if Gem::LOADED_SPECS_MUTEX.owned?
      spec.activate
    else
      Gem::LOADED_SPECS_MUTEX.synchronize { spec.activate }
    end
  end
end

Используйте Kernel#gem, чтобы активировать определённую версию gem_name.

requirements — это список требований к версии, которым должен соответствовать указанный гем; чаще всего используется запись «= example.version.number». О том, как указывать требования к версии, см. Gem::Requirement.

Если вы собираетесь активировать последнюю версию гема, вызывать Kernel#gem не нужно — Kernel#require выполнит необходимые действия.

Kernel#gem возвращает true, если гем был активирован, иначе false. Если гем не найден, не соответствует требованиям к версии или уже активирована другая версия, будет вызвано исключение.

Kernel#gem следует вызывать до любых инструкций require (иначе RubyGems может загрузить конфликтующую версию библиотеки).

Kernel#gem загружает предварительные версии, только если указаны предварительные версии requirements:

gem 'rake', '>= 1.1.a', '< 2'

В более старых версиях RubyGems переменную среды GEM_SKIP можно было использовать, чтобы пропустить активацию указанных гемов, например для тестирования ещё не установленных изменений. Теперь RubyGems использует параметры -I и переменную среды RUBYLIB, чтобы пропускать активацию гема.

Пример:

GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
j (*objs) Показать исходный код
# File ext/json/lib/json/common.rb, line 1105
def j(*objs)
  if RUBY_VERSION >= "3.0"
    warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
  else
    warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
  end

  objs.each do |obj|
    puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
  end
  nil
end

Выводит objs в STDOUT в виде строк JSON в кратчайшей форме, то есть в одну строку.

jj (*objs) Показать исходный код
# File ext/json/lib/json/common.rb, line 1120
def jj(*objs)
  if RUBY_VERSION >= "3.0"
    warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
  else
    warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
  end

  objs.each do |obj|
    puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
  end
  nil
end

Выводит objs в STDOUT в виде строк JSON в удобочитаемом формате: с отступами и в нескольких строках.

pp (*objs) Показать исходный код
# File lib/pp.rb, line 731
def pp(*objs)
  objs.each {|obj|
    PP.pp(obj)
  }
  objs.size <= 1 ? objs.first : objs
end

Выводит аргументы в удобочитаемом формате.

pp возвращает аргумент или аргументы.

require (path) Показать исходный код
# File lib/rubygems/core_ext/kernel_require.rb, line 36
def require(path) # :doc:
  return gem_original_require(path) unless Gem.discover_gems_on_require

  RUBYGEMS_ACTIVATION_MONITOR.synchronize do
    path = File.path(path)

    # If +path+ belongs to a default gem, we activate it and then go straight
    # to normal require

    if spec = Gem.find_default_spec(path)
      name = spec.name

      next if Gem.loaded_specs[name]

      # Ensure -I beats a default gem
      resolved_path = begin
        rp = nil
        load_path_check_index = Gem.load_path_insert_index - Gem.activated_gem_paths
        Gem.suffixes.find do |s|
          $LOAD_PATH[0...load_path_check_index].find do |lp|
            if File.symlink? lp # for backward compatibility
              next
            end

            full_path = File.expand_path(File.join(lp, "#{path}#{s}"))
            rp = full_path if File.file?(full_path)
          end
        end
        rp
      end

      next if resolved_path

      Kernel.send(:gem, name, Gem::Requirement.default_prerelease)

      Gem.load_bundler_extensions(Gem.loaded_specs[name].version) if name == "bundler"

      next
    end

    # If there are no unresolved deps, then we can use just try
    # normal require handle loading a gem from the rescue below.

    if Gem::Specification.unresolved_deps.empty?
      next
    end

    # If +path+ is for a gem that has already been loaded, don't
    # bother trying to find it in an unresolved gem, just go straight
    # to normal require.
    #--
    # TODO request access to the C implementation of this to speed up RubyGems

    if Gem::Specification.find_active_stub_by_path(path)
      next
    end

    # Attempt to find +path+ in any unresolved gems...

    found_specs = Gem::Specification.find_in_unresolved path

    # If there are no directly unresolved gems, then try and find +path+
    # in any gems that are available via the currently unresolved gems.
    # For example, given:
    #
    #   a => b => c => d
    #
    # If a and b are currently active with c being unresolved and d.rb is
    # requested, then find_in_unresolved_tree will find d.rb in d because
    # it's a dependency of c.
    #
    if found_specs.empty?
      found_specs = Gem::Specification.find_in_unresolved_tree path

      found_specs.each(&:activate)

    # We found +path+ directly in an unresolved gem. Now we figure out, of
    # the possible found specs, which one we should activate.
    else

      # Check that all the found specs are just different
      # versions of the same gem
      names = found_specs.map(&:name).uniq

      if names.size > 1
        raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ", "}"
      end

      # Ok, now find a gem that has no conflicts, starting
      # at the highest version.
      valid = found_specs.find {|s| !s.has_conflicts? }

      unless valid
        le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
        le.name = names.first
        raise le
      end

      valid.activate
    end
  end

  begin
    gem_original_require(path)
  rescue LoadError => load_error
    if load_error.path == path &&
       RUBYGEMS_ACTIVATION_MONITOR.synchronize { Gem.try_activate(path) }

      return gem_original_require(path)
    end

    raise load_error
  end
end

После подключения RubyGems метод Kernel#require заменяется собственной реализацией, которая умеет загружать гемы по требованию.

При вызове require 'x' происходит следующее:

  • Если файл можно загрузить из существующего пути загрузки Ruby, он загружается.

  • В противном случае среди установленных гемов ищется файл с совпадающим именем. Если он найден в геме ‘y’, этот гем активируется (добавляется в путь загрузки).

Сохраняется обычное поведение require: если файл уже был загружен, метод возвращает false.

y (*objects) Показать исходный код
# File ext/psych/lib/psych/y.rb, line 5
def y *objects
  puts Psych.dump_stream(*objects)
end

Псевдоним для Psych.dump_stream, предназначенный для использования в IRB.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API