Как группировать с помощью has_many в Rails 5 - PullRequest
0 голосов
/ 12 сентября 2018

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

class Certificate < ApplicationRecord
  has_many :certificates_users
  has_many :users, :through => :certificates_users
end

class CertificatesUser < ApplicationRecord
  belongs_to :user
  belongs_to :certificate
end

class User < ApplicationRecord
  has_many :certificates_users, :dependent => :delete_all
  has_many :certificates, :through => :certificates_users
end

Я пытаюсь получить список сертификатов, а затем сгруппировать его по пользователю. В основном перечислите всех пользователей и покажите под ними список своих сертификатов. Вот как выглядит пользовательский интерфейс Просто нажмите «Мэр» на столе.

Вот структура таблицы CertificatesUser

=> CertificatesUser(certificate_id: integer, user_id: integer, expiry_date: date, certificate_number: string, renewal_date: date, ispublic: integer)

После этого другого ответа я смог выработать эти возможные решения,

Certificate.joins(:users).group('users.id').select('users.id')

User.joins(:certificates).group('certificates.id').select('certificates.id, certificates.name')

Проблема здесь в том, что большинство полей, которые мне нужны, находятся в certificates_users, а не в таблице certificates.

Это еще одна попытка заставить это работать, но не сработало - CertificatesUser.group(:user_id).select('user.id')

Каковы другие возможные решения этой проблемы?

Желаемый вывод

enter image description here

Ответы [ 3 ]

0 голосов
/ 13 сентября 2018

Исходя из определения отношения в ваших моделях, ниже должно работать:

CertificatesUser.joins(:user, :certificate)        
    .select('user_id, users.name, users.email, certificates.name')
    .group_by(&:user_id)

Вы используете .group_by(&:user_id) для группировки выбранных данных на основе user_id в массиве json, как показано ниже:

Образец результата:

[1, [{ user_id: 1, certificate_id: 29, ....},{ user_id: 1, certificate_id: 22, ....}] ,
2, [{ user_id: 2, certificate_id: 34, ....},{ user_id: 2, certificate_id: 56, ....}] ,
3, [{ user_id: 3, certificate_id: 29, ....},{ user_id: 3, certificate_id: 12, ....}] ]

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

0 голосов
/ 13 сентября 2018

Мне удалось заставить это работать, изменив мой подход и сделав это самым простым способом.

В контроллере у меня это

@users_and_certificates = CertificatesUser.all.each_with_object({}) { |item, hash| hash[item.user_id] = item }

И затем в шаблоне я запрашиваю так:

.card-body.table-responsive
  %table.table.table-hover.table-valign-middle
    %thead
      %tr
        %th Name
        %th E-mail
    %tbody
      - @users_and_certificates.each do |user_id, certificate_object|
         %tr{"data-target" => "#certificate_#{certificate_object.certificate_id}", "data-toggle" => "collapse"}
           - user = User.find(user_id)
           %td
             = user.full_name
           %td
             = user.email
         %tr
           %td.card-body.table-responsive.collapse{'id' => "certificate_#{certificate_object.certificate_id}"}
             %table.table.table-hover.table-valign-middle
               %thead
                 %tr
                   %th Certificate
                   %th Certificate No.
                   %th Expiry Date
                   %th Certificate
               %tbody
                 %tr
                   - certificate = Certificate.find(certificate_object.certificate_id)
                   %td
                     = certificate.name
                   %td
                     = certificate_object.certificate_number
                   %td
                     = certificate_object.expiry_date
                   %td Show

Пока это работает отлично. Если у кого-то есть лучший подход, пожалуйста, не стесняйтесь оставлять комментарии или оставлять ответы.

Спасибо.

0 голосов
/ 12 сентября 2018

вы можете сделать

@users = User.includes(certificates_users: [:certificate])

, затем вы можете просмотреть их

@users.each do |u|
  u.certificates_users.each do |cu|
   cu.certificate_number
   cu.certificate.some_column
   ...
  end
end

, чтобы получить только пользователей с сертификатами

@users = User.includes(certificates_users: [:certificate]).where("certificates_users.user_id = users.id")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...