Rails, как определить, существует ли вложенный набор записей

#ruby-on-rails #ruby #ruby-on-rails-3

#ruby-on-rails #ruby #ruby-on-rails-3

Вопрос:

У меня есть следующие две модели:

 Project, has_many ProjectParticipants
ProjectParticipants, belongs_to Project
  

Как я могу запросить определение, учитывая эти 5 участников проекта, принадлежат ли они проекту?

Кроме того, это должны быть строго эти 5, не больше и не меньше.

Есть мысли о том, как элегантно решить для этого типа подсчета?

Ответ №1:

Предполагая, что participants содержит 5 участников, которых вы хотите проверить.

 participants.all? {|o| o.project }
  

Это вернет значение true для всех участников проекта, в противном случае false.

Чтобы вернуть найденный проект, вы можете сделать:

И посмотреть, все ли участники имеют один и тот же проект:

 first_participant = participants.shift

participants.all? {|o| o.project == first_participant.project} unless first_participant.nil?
  

Преимущество этого метода в том, что он замыкается, если у одного из участников нет такого же проекта (более эффективный).

Редактировать:

Чтобы вернуть проект, который они все совместно используют, вы можете сделать:

 first_participant = participants.shift

project_shared = participants.all? {|o| o.project == first_participant.project} and first_particpant.project unless first_participant.nil?
  

для project_shared будет установлен проект, к которому они все совместно используют, в противном случае он будет равен нулю / false.

Таким образом, вы можете затем сделать:

 if project_shared
  # do work
else
 # they dont share a project!
end
  

Комментарии:

1. Майк, в этом проблема, у меня нет проекта. Учитывая участников, я хочу определить, существует ли проект для этих людей или нет?

2. это, это здорово. Если совпадение действительно найдено, есть ли способ вернуть этот проект?

3. Спасибо за это, Майк, я только что попробовал это и получаю NoMethodError (неопределенный метод `project.’ для #<Пользователь: 0x10fa4de30>):

Ответ №2:

Вы можете сравнить свойства записей, участвующих в проекте, в группе:

 participants.length == 5 and participants.all? { |p| p.project_id == project.id }
  

Это подтверждает, что ваш массив участников содержит пять записей и что всем им присвоен один и тот же project_id. Сравнение p.project == project будет иметь побочный эффект загрузки одного и того же проекта пять раз.

Чтобы проверить, принадлежат ли они просто проекту, вы можете сделать это:

 participants.length == 5 and participants.all? { |p| p.project_id? }
  

Этот проект может быть удален, а ссылка может быть недействительной, поэтому вам, возможно, придется прибегнуть к фактическому извлечению его:

 participants.length == 5 and participants.all? { |p| p.project }
  

Вы также можете использовать group_by метод, чтобы увидеть, задействован ли только один проект:

 grouped = participants.group_by(amp;:project)
!grouped[nil] and grouped.length == 1 and grouped.first[1].length == 5
  

group_by Метод организует данный массив в хэш, где ключ указан в качестве параметра, а значение представляет собой список совпадающих объектов. Это может быть удобно в подобных ситуациях.

Комментарии:

1. спасибо, но я не уверен, что это сработает. Учитывая 5 человек и ничего не зная о проекте. Я хочу определить, принадлежат ли эти 5 человек уже существующему проекту в БД. Мысли?

2. Я добавил обновление. Ваш вопрос был не очень ясен в деталях.