Reputation: 1396
I'm running into several syntax and nil issues when trying to create this hash idea_benefit_count
.
@idea = @domain.ideas
@idea_evaluations = Array.new()
@idea.each do |idea|
@idea_evaluations << idea.evaluations
end
@idea_benefit = []
if !@idea_evaluations.nil?
@idea_evaluations.each do |eval|
@idea_benefit << eval.benefit
end
@idea_benefit_count = Hash.new(0)
@idea_benefit.flatten.each { |idea_benefit| @idea_benefit_count[idea_benefit] += 1 }
end
An idea has_many domains
, so @idea
should be all of the ideas that has a given @domain
.
@idea_evaluations
is an array of all evaluations that belong_to
a specific idea
.
@idea_benefit
is an array of arrays that holds all of each evaluation's benefit
entries. example output: [["happier_customers"], ["happier_employees"], ["happier_employees", "decreased_costs"], ["happier_employees"]]
idea_benefit_count
reads idea_benefit
and counts how many of each type of benefit an idea has. The output of idea_benefit_count
based on the above idea_benefit
array is {"happier_customers"=>1, "decreased_costs"=>1, "happier_employees"=>3}
(Hopefully this context covers everything)
My current error is undefined method 'benefit'
on the line @idea_benefit << eval.benefit
. Benefit
is an attribute of evaluation
, so it should output something like ["happier_customers"]
.
I realize this code is a bit of a mess, so any suggestions would be super helpful on getting the entire thing working. A big problem is checking to see if there are evaluations
belonging to an idea
, because if this comes back nil
it throws an error. Tried to fix that with the if !@idea_evaluations.nil?
check, but haven't been able to test it yet because of the undefined method 'benefit'
error.
EDIT
@idea_evaluations = Array.new()
@idea.each do |idea|
@idea_evaluations << idea.evaluations
end
@idea_evaluations.flatten!
@idea_benefit = []
unless !@idea_evaluations.nil?
@idea_evaluations.each do |eval|
@idea_benefit << eval.benefit
end
@idea_benefit_count = Hash.new(0)
@idea_benefit.flatten.each { |idea_benefit| @idea_benefit_count[idea_benefit] += 1 }
end
Upvotes: 1
Views: 138
Reputation: 7203
I believe this entire snippet can be replaced by:
@idea_benefit_count =
@idea.flat_map(&:evaluations)
.flat_map(&:benefit)
.each_with_object(Hash.new{0}) {|k, h| h[k] += 1}
Upvotes: 0
Reputation: 3870
Use map
to build up the array (or an ActiveRecord scope for better efficiency).
@idea_evaluations = @domain.ideas.map(&:evaluations)
# Remove nil values before moving on to the next chunk.
@idea_evaluations.reject! { |i| i.nil? }
@idea_benefits = @idea_evaluations.map(&:benefit)
If you go with the scope approach, it would look similar to the following:
# in Benefit.rb
scope for_domain ->(domain_id){ joins(:evaluation => :idea).where(idea: {domain_id: domain_id}) }
# called like this
@idea_benefits = Benefit.for_domain(@domain.id)
inject
is a useful tool to summarize information.
@idea_benefits .inject({}) do |eval, result|
result[eval] += 1
result
end
Upvotes: 0
Reputation: 10566
the problem that I see if I understand what you are trying to do is the way you are dumping idea.evaluations into @idea_evaluations.
@idea_evaluations is going to be an array of arrays of evaluations not an array of evaluations as you think.
e.g. [[eval1,eval2],[eval3,eval4,eval5]]
instead of [eval1, eval2, eval3, eval4, eval5]
when you try to access the benefit, it attempts to look for a benefit method for the array which does not exist.
try altering
@idea.each do |idea|
@idea_evaluations << idea.evaluations
end
to be
@idea.each do |idea|
@idea_evaluations << idea.evaluations
end
@idea_evaluations.flatten!
also in ruby you usually don't do
if !condition
you normally do
unless condition
Upvotes: 1