rails 中的 "invalid slice size" 错误是什么? - @categories.each_slice(column_length) 做|列|使用此代码发生。

What is an "invalid slice size" error in rails? - @categories.each_slice(column_length) do |column| Happens w/ this code.

获得"invalid slice size"

全新 rails。在前端玩耍。

- column_length = @categories.length.fdiv(3).ceil
- @categories.each_slice(column_length) do |column|

此代码产生错误。它似乎在 运行 网站上运行良好。到目前为止,我唯一想到的就是编辑导航和 bootstrap 布局。

什么会导致此错误,即保持页面表单呈现?

嗯,我重现了错误:

[1,2,3].each_slice(0.22222222).to_a
# ArgumentError: invalid slice size
[1,2,3].each_slice(0).to_a
# ArgumentError: invalid slice size
[1,2,3].each_slice(-1).to_a
# ArgumentError: invalid slice size

#each_slice 会将其参数作为 Fixnum 个实例,但 0 或任何 负数 除外。 #each_slice 总是试图通过使用 Kernel#Integer 方法将其参数转换为 Fixnum,并且在这样做之后如果它得到 0 或任何 负数 , 它会抛出你遇到的错误。如果 argument#each_slice 方法不能转换为 integer ,它会给你下面的内容:

[1,2,3].each_slice([1]).to_a
# TypeError: no implicit conversion of Array into Integer
[1,2,3].each_slice(Object.new).to_a
# TypeError: no implicit conversion of Object into Integer

但你给它一个 Float 点数,如下所示,在 类型转换后 给你一个 Fixnum 实例,但不是 0, 将正常工作:

[1,2,3].each_slice(2.22222222).to_a
# => [[1, 2], [3]]

现在,在你的情况下 @categories.length.fdiv(3).ceil 给你一些东西 0 或任何 负数 ,并且 #each_slice 的参数值导致错误。

好吧,我从 official documentation

中找到了 C 代码
static VALUE
enum_each_slice(VALUE obj, VALUE n)
{
    long size = NUM2LONG(n);
    VALUE ary;
    NODE *memo;
    int arity;

    if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
    RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
    ary = rb_ary_new2(size);
    arity = rb_block_arity();
    memo = NEW_MEMO(ary, dont_recycle_block_arg(arity), size);
    rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
    ary = memo->u1.value;
    if (RARRAY_LEN(ary) > 0) rb_yield(ary);

    return Qnil;
}

所以,为什么 [1,2,3].each_slice(0.22222222).to_a 导致错误 - ArgumentError: invalid slice size :

嗯,从MRI源码可以看出,n(意思是0.22222222)已经传给了函数NUM2LONG()。现在,如果您查看函数的 Rubinius implementation,您会发现

def self.num2long(obj)
  if obj == nil
    raise TypeError, "no implicit conversion from nil to integer"
  else
    Integer(obj)
  end
end

这段代码非常清楚地说明了 NUM2LONG() 函数内部发生了什么。现在,让我们尝试 3 个示例 n 值,正如我在 IRB 中重现错误的前 3 个示例中使用的那样:

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

这就是 n = 0.22222 在 MRI 中 size 被函数 NUM2LONG(n) 分配为 0 的方式。 值触发错误。