Rails Active Record: найти в сочетании с: order и: group - PullRequest
1 голос
/ 15 июля 2009

У меня есть что-то вроде структуры:

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 ]

3 голосов
/ 15 июля 2009

В ваших моделях вся информация об ассоциации уже объявлена. На самом деле вы можете использовать каждого пользователя для доступа к информации о ключах и лицензиях, выполнив один запрос с ActiveRecord , включая опции.

# 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

0 голосов
/ 15 июля 2009

Вы пробовали с областью по умолчанию? Во-первых, вы можете попытаться добавить порядок в 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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...