Ruby on rails 4 Rails 4为对象加载

Ruby on rails 4 Rails 4为对象加载,ruby-on-rails-4,rails-activerecord,eager-loading,Ruby On Rails 4,Rails Activerecord,Eager Loading,我正在尝试从实例化的对象中加载关联,即,而不是与父对象一起读取关联 User.includes(:characters).first …将其推迟到我确定确实需要时,然后执行以下操作: u = User.first # Other stuff ... u.eager_load(:characters) 在Rails 3中,我使用以下方法增强了ActiveRecord: def eager_load(*args) ActiveRecord::Associations::Preloader.n

我正在尝试从实例化的对象中加载关联,即,而不是与父对象一起读取关联

User.includes(:characters).first
…将其推迟到我确定确实需要时,然后执行以下操作:

u = User.first
# Other stuff ...
u.eager_load(:characters)
在Rails 3中,我使用以下方法增强了ActiveRecord:

def eager_load(*args)
  ActiveRecord::Associations::Preloader.new(self, *args).run
end
而且效果很好。Rails 4稍微改变了这一部分,我将方法更新为:

def eager_load(*args)
  ActiveRecord::Associations::Preloader.new.preload(self, *args)
end
不幸的是,它现在做了一些奇怪的事情。看一看:

2.1.2 :001 > u = User.first
[2015-01-06 23:18:03] DEBUG ActiveRecord::Base :   User Load (0.3ms)  SELECT  `users`.* FROM `users`  ORDER BY `users`.`id` ASC LIMIT 1
 => #<User id: 1, ...> 
2.1.2 :002 > u.eager_load :characters
[2015-01-06 23:18:07] DEBUG ActiveRecord::Base :   Character Load (0.2ms)  SELECT `characters`.* FROM `characters` WHERE `characters`.`user_id` IN (1)
[2015-01-06 23:18:07] DEBUG ActiveRecord::Base :   Character Load (0.3ms)  SELECT `characters`.* FROM `characters`
[2015-01-06 23:18:07] DEBUG ActiveRecord::Base :   Character Load (0.2ms)  SELECT `characters`.* FROM `characters`
 => [#<ActiveRecord::Associations::Preloader::HasMany:0x00000007c26d28 @klass=Character(id: integer, ...), @owners=[#<User id: ...], @reflection=#<ActiveRecord::Reflection::HasManyReflection:0x0000000496aa60 @name=:characters, ...(LOTS of stuff here)...] 

请特别注意所有记录的双重选择。有没有办法修复这种行为或其他方法来实现我想要的功能?

要避免重复查询,您应该立即加载您认为将要使用的所有内容。因此,您应该将include命令嵌套在:

您还可以添加更深层次的关系,如:

users = User.includes(:address, {friends: [:address, :followers]})

我也遇到了同样的问题,追溯我的步骤,我注意到这可能是在控制台上运行此代码的一个工件。每个表达式都会被计算,但我们只对副产品感兴趣:如果是这种情况,请尝试:

u.eager_load(:characters); nil

我希望它能有所帮助,我目前正在研究这个问题,因此这是我目前为止唯一的观察结果。

在您的示例中,为什么不希望将关联与父对象一起读取?为什么你可以直接调用u.characters?这是否符合只在你需要字符时才获取字符的情况?这只是为了说明问题。我可能希望预加载更深层次的结构,例如字符:{items::attributes},以防止N+1查询。我无法理解IncludeCharacter:{items::attributes}不够用的用例?如果满足某些条件,我可能只需要字符、项目和属性。我仍然需要单独加载用户来检查这种情况。我在Rails 4.2.6上也有同样的问题,您使用的是什么版本?正确的查询发生在两次加载整个表之后,删除WHERE子句。这正是我想要避免的-我想推迟加载依赖对象,直到结果证明我需要它们。因此,您只需要通过关联方法调用它们:例如User.first.address。@Hamdam,实际上,他使用的不是单个用户,而是多个用户;在您的示例中,如果不立即加载,则会发生N个额外的查询,以加载地址。是的,这会有所帮助,不必要的查询也会消失。是的,我在服务器日志中检查过,事实上这根本没有发生。但我不明白这里发生了什么。有无评估什么;nil…?我的猜测是预加载程序对象在调用时返回。从现在开始,预加载类似于ActiveRecord::Relation。在控制台中,如果您一步一步地构建一个关系,那么每次都会执行查询,因为每个语句都会在控制台中返回,但在服务器中,您构建了一个关系,并且只在请求结果循环时才运行它,等等。为了清楚起见,您不需要;服务器上为零,只有控制台。显然,这在Rails5上不起作用。有其他选择吗?我没有,但是如果该方法不再存在,那么当它被删除时,您应该在Rails的Github中跟踪它。我相信你能找到另一种方法。如果你能确切地告诉我们什么是不起作用的,这会有帮助的?你有错误吗?什么错误?如果你的设置太不同了,你可能想考虑发布你自己的问题。
u.eager_load(:characters); nil