如何从`has_many`关联中加载一行

时间:2014-01-14 09:35:32

标签: ruby-on-rails database activerecord

我有这些模型

class User < ActiveRecord::Base
  has_many :agent_logins

  def active_login
    agent_logins.active.order('created_at DESC').first
  end 
end

class AgentLogin < ActiveRecord::Base
  belongs_to :user
  scope :active, -> { where(active: true) }
end

我有这个带有此序列化程序的API控制器

class API::UsersController < API::APIController
  def index
     respond_with User.all
  end
end

class UserSerializer < ActiveModel::Serializer
  attributes :id, :pin, :voicemail, :name, :active_login
end

这个cource产生了N + 1问题

User Load (7.7ms)  SELECT `users`.* FROM `users`
  AgentLogin Load (2.7ms)  SELECT `agent_logins`.* FROM `agent_logins` WHERE `agent_logins`.`user_id` = 3 AND `agent_logins`.`active` = 1 ORDER BY created_at DESC LIMIT 1
  AgentLogin Load (3.8ms)  SELECT `agent_logins`.* FROM `agent_logins` WHERE `agent_logins`.`user_id` = 16 AND `agent_logins`.`active` = 1 ORDER BY created_at DESC LIMIT 1
  AgentLogin Load (3.8ms)  SELECT `agent_logins`.* FROM `agent_logins` WHERE `agent_logins`.`user_id` = 18 AND `agent_logins`.`active` = 1 ORDER BY created_at DESC LIMIT 1

有没有一种解决这个问题的首选方法?谢谢。

1 个答案:

答案 0 :(得分:0)

尝试这个非常不优雅的解决方案。

创建一个名为ActiveLogins的单独类

class User
  has_one :active_login
end

class ActiveLogins 
  belongs_to :user #=> foregin key :user_id 
end

每次创建AgentLogin时,您也会创建一个相同的ActiveLogin并删除所有其他具有相同ActiveLogin的ActiveLogin:user_id

然后你可以调用User.all.includes(:active_login)(希望没有N + 1问题)