Relation.all 在 Rails 4 中弃用

Relation.all deprecation in Rails 4

如果我在 Rails 3 中执行以下操作:

users=User.where("last_name like ?","s%").all

它 returns 是一个数组,我可以通过执行以下操作立即将其视为数组:

users.unshift(User.new)

在Rails 4中.all语句给出弃用警告:

DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load

所以现在 .all 正在返回一个关系,大概以下两行代码是等价的:

users=User.where("last_name like ?","s%").all

users=User.where("last_name like ?","s%")

换句话说,变量 'users' 现在是关系而不是数组。

我的问题是,是什么魔法使关系能够被视为数组,因为 'users.unshift' 语句仍然作用于关系并将其转换为数组。它是在强制加载关系吗?

我真的应该使用“.load”吗?它似乎不是必需的,但逻辑上应该是。

ActiveRecord::Relation 使用 method_missing 将大多数数组方法委托给 Array。 unshift 就是其中之一。

在此处查看来源:https://github.com/rails/rails/blob/1361b676d3a51aa0fca299f432e75032dd29a9d9/activerecord/lib/active_record/relation/delegation.rb#L128

def array_delegable?(method)
  Array.method_defined?(method) && BLACKLISTED_ARRAY_METHODS.exclude?(method)
end

def method_missing(method, *args, &block)
  if @klass.respond_to?(method)
    scoping { @klass.public_send(method, *args, &block) }
  elsif array_delegable?(method)
    to_a.public_send(method, *args, &block)
  elsif arel.respond_to?(method)
    arel.public_send(method, *args, &block)
  else
    super
  end
end

查看ptd的评论

ActiveRecord collections act like arrays, so you can call any array methods on them (although they will turn it into an array so you'll lose the special ActiveRecord methods). You don't have to call #load to have it act like an array. Just pretend that the ActiveRecord collection is an array and you'll be fine