0

У меня есть следующая структура модели: у карнавала есть много событий, в которых много конкурентов. Участник имеет полиморфного Участника, который является либо Студентом, либо Командой (в которой много учеников). В коде:Rails: как добавить атрибут sum из полиморфно ассоциированной модели к записям записей

class Carnival < ActiveRecord::Base 
    has_many :events 
end 

class Event < ActiveRecord::Base 
    belongs_to :event_type 
    belongs_to :division 
    has_and_belongs_to_many :genders 
    has_and_belongs_to_many :grades 
    has_many :competitors 
    has_many :students, through: :competitors, :source => :participant, :source_type => 'Student' 
    belongs_to :carnival 
end 

class Competitor < ActiveRecord::Base 
    belongs_to :event 
    belongs_to :participant, polymorphic: true 
    belongs_to :grade 
    belongs_to :house 
end 

class Team < ActiveRecord::Base 
    has_one :competitor, :as => :participant 
    has_one :event, :through => :competitor 
    has_and_belongs_to_many :students 
end 

class Student < ActiveRecord::Base 
    belongs_to :grade 
    belongs_to :house 
    belongs_to :gender 
    has_many :competitors, :as => :participant 
    has_many :events, :through => :competitors 
    has_many :carnivals, :through => :events 
    has_and_belongs_to_many :teams 
end 

На Конкурсанте есть атрибут точек, так что после того, как на него будут назначены очки выполнения.

Что я хотел бы, это серия методов, которые дадут мне всех учеников вместе с их точками.

Student.with_total_points_for_carnival(c) 
Student.with_individual_points_for_carnival(c) 
Student.with_team_points_for_carnival(c) 

Я получил некоторые SQL, что делает общее количество очков (хотя я немного неудобно, как/если он работает должным образом, так как я только действительно наткнулся на него):

SELECT 
    name, 
    SUM(points) as points 
FROM 
    public.students_teams, 
    public.students, 
    public.teams, 
    public.competitors, 
    public.events 
WHERE 
    students_teams.team_id = teams.id AND 
    students.id = students_teams.student_id AND 
    competitors.participant_id = teams.id AND 
    events.id = competitors.event_id AND 
    carnival_id = 1 
GROUP BY 
    public.students.id 
ORDER BY 
    points DESC 

Это дает общее точки. Мои Рельсы попытке дать мне результаты, но они не являются правильными, и они не являются студенческими записями либо:

def self.with_total_points_for(carnival) 
    Student. 
    joins(:competitors, :events, teams: { competitor: :event}). 
    where('events.carnival_id = ?', [carnival.id]). 
    group('students.id'). 
    sum('competitors.points') 
end 

Любого руководство о том, как получить эту работу? Так что я мог бы пойти:

<% Student.with_total_points_for(@carnival).each do |s| %> 
    <%= s.name %>: <%= s.total_points %> <br> 
<% end %> 

Еще лучше было бы функция или сфера, как Student.with_all_points_for, которые позволили бы мне сделать:

<% Student.with_all_points_for(@carnival).each do |s| %> 
    <%= s.name %>: <%= s.total_points %>/<%= s.individual_points %>/<%= s.team_points %> <br> 
<% end %> 

но ребенка-шаги на данный момент ...

ответ

0

I я не уверен, что правильно поймал вашу цель, но я думаю, это может вам помочь

Добавить необходимые поля в select

def self.with_total_points_for(carnival) 
    Student. 
    joins(:competitors, :events, teams: { competitor: :event}). 
    where('events.carnival_id = ?', [carnival.id]). 
    group('students.id'). 
    select('students.*, SUM(competitors.points) AS total_points') 
end 

Некоторые примечания:

  1. (я не проверял, но у меня есть подобный вопрос раньше), если вы используете Postgres вы не должны использовать students.* вы должны перечислить все необходимые столбцы непосредственно: select('students.id, students.name, ..., total_points')
  2. (это может быть полезно) вы можете перечислить в select столбцы из участвующих таблиц, но помните, что вы используете group в запросе

PS Я не уверен, что есть простой способ получите individual_points и team_points в одном простом запросе. Я думаю, вы должны использовать подзапросы для этих целей и вставлять их в основной запрос. Будьте осторожны, потому что это может быть тяжелый запрос к БД, и потребуется оптимизация.

Смежные вопросы