1

У каждого пользователя может быть много ресурсов, и каждый из этих ресурсов имеет много голосов, и каждый из этих голосов имеет атрибут value, который я хочу суммировать для всех этих конкретных ресурсов пользователей.Как суммировать много-много значение?

Если я печатаю это в синтаксически неверный путь, я хочу что-то вроде ...

@user.resources.votes.sum(&:value), но это, очевидно, не будет работать.

Я считаю, что мне нужно использовать collect, но я не уверен?

Это ближайший я получил, но он печатает их, хе

<%= @user.resources.collect { |r| r.votes.sum(&:value) } %>

ответ

2

Как вы можете сказать, кто голосовал, имеющий экземпляр Vote? Ваша модель Vote должна иметь voter_id поле и дополнительные ассоциации:

# in Vote.rb 
belongs_to :voter, class_name: 'User', foreign_key: 'voter_id' 

И в модели пользователя:

# in User.rb 
has_may :submited_votes, class_name: 'Vote', foreign_key: 'voter_id' 

Так, @user.votes (как предложил Дэвид Underwood) даст вам @user голоса ресурсов. И @user.submited_votes подарит вам голоса, представленные пользователем @user.

Использование только пользователем < - Ресурс < - Отношение голосов не позволит вам отбирать голоса некоторых пользователей, сделанные им, и голоса, полученные за его ресурсы.

+0

Извините, я не понимаю, что вы имеете в виду. То, что я хочу сделать, это по существу sum = 0; @ user.resources.each do {| resource | sum + = resource.votes.sum (&: value)} – Tallboy

+0

Этот код работает, но слишком долго, я просто хотел написать все это на одной строке – Tallboy

+0

Если у вас правильно заданные отношения, вы сможете рассчитать сумму по '@ user.votes.sum (: value)'. – jdoe

1

Для общей суммы это должно работать или что-то очень близко.

sum = 0 
@user.resources.each do |r| 
r.votes.each do |v| 
    sum += v.value 
end 
end 

Это может работать для вас:

@user.resources.map {|r| r.votes.sum(:value)}.sum 

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

+0

, который будет работать, но я стараюсь соответствовать всем этим на одной линии, в идеале используя какой-то Proc, просто чтобы сохранить эту часть моего кода чистым – Tallboy

+0

@Tallboy, я пошел дальше и обновил свой ответ выше, чтобы включить один лайнер ... – tronmcp

3

Я бы рекомендовал установить связь между объектами User и Vote: has_many :through. Установите модели вверх, как это:

class User < ActiveRecord::Base 
    has_many :resources 
    has_many :votes, :through => :resources 
end 

class Resource < ActiveRecord::Base 
    belongs_to :user 
    has_many :votes 
end 

class Vote < ActiveRecord::Base 
    belongs_to :resource 
end 

Как только это будет сделано, вы можете просто позвонить user.votes и делать все, что вы хотите с этой коллекцией.

Для получения дополнительной информации о has_many :through отношений см это руководство: http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

+0

Извините за недоразумение, я не уверен, что то, что вы сказали, по-прежнему применяется. У меня есть отношения, но я пытаюсь подсчитать все «глобальные» голоса за все ресурсы, предоставленные пользователем (все голоса других людей на тех людских ресурсах). Если я сделаю Пользователь.голосует только за талис голосов, созданных этим лицом – Tallboy

1

Попробуйте этот код

@user.resources.map(&:votes).flatten.map(&:value).sum 
+0

Эффективный, но, возможно, катастрофический по поводу того, что он вызвал SQL, нет? – Phrogz