1

I'm building a league system and currently it stores and updates the players 'elo score' depending on the result. Now, I'm trying to add in 'HighCharts' to display the players elo score over the season in a sweet looking line chart. Someone suggested I use Papertrail to store the updates and I have got that all installed.

Now here comes my problem, I can't seem to figure out how to spit out the users elo_score versions in an array easy for 'HighCharts' to use. I can get the last updates to elo_score:

Last updated score = <%= @player.versions.last.reify.elo_score %> 

But I can't seem to find the syntax to spit out all the 'versions' for 'elo_score'. Something like "1000, 1020, 1043, 1020".

I've also tried:

<%= @player.versions.map { |version| version.reify.elo_score} %>

But this gives me "undefined method `elo_score' for nil:NilClass". While just <%= @player.versions.map { |version| version.reify %> spits out all information in the record and obviously not just the elo_score.

Can anyone help? Sorry if I've not made this clear, I'm absolute brand new to rails, and this is just a fun project in my spare time but I'm having a blast!

Thanks alot!

Martin
  • 55
  • 1
  • 9

2 Answers2

4

What you did here:

@player.versions.map { |version| version.reify.elo_score }

Is perfectly fine to take all those scores and put them in an array. The problem that you're getting (the nil:NilClass stuff) is coming because at least one reify is nil. That is, that some version doesn't have a reify.

If each version is supposed to have a reify, be sure to add that as a model validation, and find in your code where the reify is being set and see why it's nil.

If it's okay for a version to have a nil reify, you could accomplish it a number of ways, but the straightforward and explicit way would look like this:

elo_scores = []
@player.versions.each do |version|
    unless version.reify.nil?
        elo_scores << version.reify.elo_score
    end
end

I would suggest putting this in to a method, like get_elo_scores, and then you could more easily call it like:

@player.get_elo_scores

EDIT For clarification from the comments:

Your User model (or Player model, whatever you named it) should have a method that looks like this:

def get_elo_scores
    elo_scores = []
    self.versions.each do |version|
        unless version.reify.nil?
            elo_scores << version.reify.elo_score
        end
    end
    return elo_scores
end

I apologize for not making this clearer, but you won't have access to @player within this method because that only exists in the context of your controller and view. The above is now a proper instance method: it will call .versions upon itself, and the rest is fine. I also added an explicit return call at the end.

Now you will be able to call @player.get_elo_scores on any User (or Player) object.

Hope that helps!

MrDanA
  • 11,489
  • 2
  • 36
  • 47
  • Thanks for your help @MrDanA. Just to make things clear, I should put def get_elo_scores elo_scores = [] @player.versions.each do |version| unless version.reify.nil? elo_scores << version.reify.elo_score end end end in my players model, and call <%= @player.get_elo_scores %> in my view? I just tried this and I get 'undefined method `versions''. What you said makes perfect sense, and yes, it's find if I have a nil reify. Thanks for your time, really appriciated! – Martin May 18 '12 at 13:34
  • Thank you so much for taking out your time to help me out! That works perfect! – Martin May 18 '12 at 14:17
  • Infact @MrDanA, little problem. It's not currently adding the newest version to the array, just the previous versions. I've played around but I seem to be messing the order around! for example, its coming up "[1000, 992]" when it should be "[1000, 992, 990]". – Martin May 18 '12 at 14:36
  • You're welcome! As for your last comment, `self.versions` will grab all the versions as long as they are saved properly and attached to the user. Perhaps the latest version is not saved? Perhaps it has a nil `reify` and therefore is not being put in the array of scores? – MrDanA May 18 '12 at 14:38
  • Hmm, I suppose it wouldn't be created as a 'version' until a new score has been updated? I can call @player.elo_score and get the '990'. Not until there is a newer score will it show up in the array. – Martin May 18 '12 at 14:47
  • since ruby 2.3.0 you can just use safe navigator(&) : `@player.versions.map { |version| version.reify&.elo_score }` – tetiross Nov 09 '17 at 11:28
0

Here's a one-liner version of @MrDanA's answer :

elo_scores = self.versions.map{|version| version.reify.elo_scores}

note that you can't check if version.reify.nil? though