Question

Each User can have many Resources, and each of those Resources has many Votes, and each of those votes have a value attribute that I want to sum all that particular users resources.

If I were to type this in a syntactically incorrect way I want something like...

@user.resources.votes.sum(&:value), but that obviously won't work.

I believe I need to use collect but I am not sure?

This is the closest I got but it prints them out, heh

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

Was it helpful?

Solution

How can you tell who voted having a Vote instance? Your Vote model has to have voter_id field and additional association:

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

And in your User model:

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

So, @user.votes (as David Underwood proposed) will give you @user resources' votes. And @user.submited_votes will give you votes submitted by the @user.

Using just User <- Resource <- Vote relation won't allow you to separate some user's votes made by him and votes made for its resources.

OTHER TIPS

I'd recommend setting up a has_many :through relationship between the User and Vote objects. Set the models up like this:

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

Once this is done you can simply call user.votes and do whatever you want with that collection.

For more info on has_many :through relations, see this guide: http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

For a total sum this should work or something real close.

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

This might work for you:

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

How many records do you have, there is a way to push this to the database level I believe, I would have to check, but if it is only a few records then doing this in ruby would probably be ok

Try this code

@user.resources.map(&:votes).flatten.map(&:value).sum
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top