Richlewis
Richlewis

Reputation: 15384

has_many association between models

I have a rake task that allocates a score when comparing a prediction and result, at the moment the relationship is a has_one, as in a prediction has_one :result..

I want to change this to a prediction has_many :results. My task looks like this

namespace :grab do
 task :scores => :environment do
  Prediction.all.each do |prediction|
   score = points_total prediction, prediction.result
   allocate_points prediction, score
  end
 end
end

def points_total(prediction, result)
  wrong_predictions = [prediction.home_score - result.home_score, prediction.away_score - result.away_score]
  wrong_predictions = wrong_predictions.reject { |i| i == 0 }.size # returns 0, 1 or 2
   case wrong_predictions
    when 0 then 3
    when 1 then 1
    else 0
  end
 end

 def allocate_points(prediction, score)
  prediction.update_attributes!(score: score)
end

At the moment when running the task i get the error

undefined method result for Prediction Class

So with the has_many relationship would i be able to access the result attributes via

prediction.result.home_score

or am i getting confused somewhere. I dont know how to refactor my rake task to fit in with the new relationship

Any advice appreciated

EDIT

even after receiving the below advice from @andrunix cant seem to figure out how to apply to the rake task , this is what i have so far but get error undefined method to_i for array

namespace :grab do
 task :scores => :environment do
  Prediction.all.each do |prediction|
   score = points_total prediction
   allocate_points prediction, score
  end
 end
end

def points_total prediction
 prediction.results.each do |result|
  result_h = result.home_score
  result_a = result.away_score
  wrong_predictions = [prediction.home_score - result_h, prediction.away_score - result_a]
  wrong_predictions = wrong_predictions.reject { |i| i == 0 }.size # returns 0, 1 or 2
  case wrong_predictions
  when 0 then 3
  when 1 then 1
  else 0
  end
 end
end

 def allocate_points prediction, score
  prediction.update_attributes!(score: score)
 end

Upvotes: 0

Views: 66

Answers (1)

andrunix
andrunix

Reputation: 1754

If a prediction :has_many results, then results is now a collection and you'll have to treat it as such. You can't say,

prediction.result.home_score

You have to reference results with an array index like,

prediction.results[0].home_score

Or iterate over the collection of results like:

prediction.results.each do |result|
    result.home_score # do something with the score
end

I realize this doesn't totally answer the "how to refactor" question but if a Prediction :has_many results, you can't simply reference prediction.result anymore.

Hope that helps.

Upvotes: 1

Related Questions