Rails Activerecord:与:order和:find一起查找

时间:2009-07-15 06:50:25

标签: ruby-on-rails ruby activerecord

我的结构是这样的:

class User
  has_many :dongles
  has_many :licences, :through => :dongles
end

class Dongle
  has_many :licences
  belongs_to :user
end

class Licence
  belongs_to :dongle
end

然而,时间过去了,用户最终会获得每个加密狗的多个许可证。合理地,该应用程序想要总结每个许可证的最新许可证。

我知道我可以天真地这样做:

user.dongles.each do |dongle|
  licence = dongle.licences.find(:first, :order => 'created_at DESC')
  # do something with the licence info
end

但有没有办法通过集合来实现这一点,并避免通常以天真的方式做出的大量查询?

我试过了:

user.licences.find(:all, :order => 'created_at DESC', :group => 'dongle_id')

这确实会为每个加密狗返回一个许可证,但它所采用的第一个许可证由'id'决定,不是由我在查询中指定的顺序决定。

我有没有办法让它给我第一个,使用我提供的排序顺序来决定哪个是第一个?

2 个答案:

答案 0 :(得分:3)

从您的模型中,已经声明了所有关联信息。通过使用ActiveRecord include 选项执行单个查询,您实际上可以使用每个用户访问加密狗和许可证信息。

# Say the table name is licences and dongles.
users = User.find(:all, 
  :include => [:dongles, :licences], 
  :order => "licences.created_at DESC, dongles.created_at DESC")

我假设您要创建每个用户拥有的每个加密狗的最新许可证摘要。你可以根据实际需要减少循环。

users.each do |user| 
  # do something with your user info
  user.dongles.each do |dongle|
    # do something with your dongle info
    licence = dongle.licences.first
    # do something with the licence info
  end
end

http://snippets.dzone.com/posts/show/2089

了解详情

答案 1 :(得分:-1)

您是否尝试过默认范围? 首先,您可以尝试在has_many中添加订单,如我在User中所示。

class User
  has_many :dongles
  has_many :licences, :through => :dongles, :order => 'created_at DESC'
end

但是,我不确定这是否真的适用于多次通过关联,也许,如果这不起作用,您可以尝试将其添加到Dongle中的关联。

class Dongle
  has_many :licences, :order => 'created_at DESC'
  belongs_to :user
end

第二种选择是尝试使用默认范围,如我在许可证中所示。

class Licence
  default_scope :order => 'created_at DESC'
  belongs_to :dongle
end

之后,只需使用user.licenses.find(:first)

就可以了