Подтвердить что ты не робот

Массивы в Ruby: Take vs Limit vs First

Предположим, у вас есть массив объектов в Rails @objects

Если я хочу отобразить первые 5 объектов, в чем разница между использованием:

  • @objects.limit(5)
  • @objects.take(5)
  • @objects.first(5)

Я говорю об интерфейсе (Ruby), НЕ SQL. Причина, по которой объекты не ограничены в SQL, заключается в том, что один и тот же массив можно использовать в другом месте, не применяя к нему ограничение.

Имеет ли это какое-либо отношение к созданию объекта?

4b9b3361

Ответ 1

  • limit не является методом массива
  • take требует аргумента; он возвращает пустой массив, если массив пуст.
  • сначала можно вызвать без аргумента; он возвращает nil, если массив пуст и аргумент отсутствует.

Источник для 2.0 take

              static VALUE
rb_ary_take(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }
    return rb_ary_subseq(obj, 0, len);
}

Источник для 2.0 сначала:

              static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
    if (argc == 0) {
        if (RARRAY_LEN(ary) == 0) return Qnil;
        return RARRAY_PTR(ary)[0];
    }
    else {
        return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    }
}

В терминах Rails:

  • limit(5) добавит область limit(5) к ActiveRecord::Relation. Он не может быть вызван в массив, поэтому limit(5).limit(4) завершится с ошибкой.

  • first(5) добавит область limit(5) к ActiveRecord::Relation. Он также может быть вызван в массиве, поэтому .first(4).first(3) будет таким же, как .limit(4).first(3).

  • take(5) выполнит запрос в текущей области, построит все объекты и вернет первые 5. Он работает только с массивами, поэтому Model.take(5) не будет работать, хотя остальные два будут работать.

Ответ 2

Выбранный ответ кажется устаревшим (с точки зрения Rails), поэтому я хотел бы обновить некоторую информацию.

  1. limit на ActiveRecord::Relation прежнему будет Relation. Так что если вы позвоните:
Model.limit(5).limit(4)

будет таким же как:

Model.limit(4)
  1. first в ActiveRecord::Relation сделает результат Array. Таким образом, вы не можете вызвать любую область после first как:
Model.first(5).where(id: 1)

Но вы можете сделать это:

Model.limit(5).where(id: 1)
  1. take
Model.take(5)

работает сейчас. Он вернет массив, так что вы также не можете вызвать какую-либо scope.


В объекте ActiveRecord::Relation, если вы ORDER BY 'tables'.id first он будет включать ORDER BY 'tables'.id. С помощью limit и take ORDER BY включается, но сортировка зависит от реализации сортировки базы данных.