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 就是其中之一。
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
如果我在 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 就是其中之一。
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 specialActiveRecord
methods). You don't have to call#load
to have it act like an array. Just pretend that theActiveRecord
collection is an array and you'll be fine