2

I have been doing a little reading up on Ruby. Like how simplistic the language is. I've been trying to look it up, and figure it out on my own. I'm looking for some help with Objects and how I add data to it. I want to make an Object called Athlete where I read it in from a .txt or .csv file their Jersey Number and Name.

class Athlete
  def setNumber (jNum)
    @mynum = jNum
  end

  def getNumber
    return @mynum
  end

  def setName (jName)
    @myname = jName
  end

  def getName
    return @myname
  end
end

Is that how I would set up the class?

Then I read in the file:

myAthlete = Athlete.new

fileObj = File.new(uInput, "r")
while (line = fileObj.gets)
  jData = line.split(" ")
  myAthlete.setNumber(jData.at(0))
  myAthlete.setName(jData.at(1))
end
fileObj.close

this is where I start to get a bit lost. I know it splits the data perfectly, because I've already tried this with just Array.new -- That being said, I'm trying to make the array inside of the Athlete class. Can someone assist me with this?

So if my input file is:

52 Sabathia
19 Tanaka
17 Holliday
24 Sanchez

I would like for it to split and then if I call lets say uhhh myAthlete(1) it'd print out Tanaka's stuff

2 Answers 2

5

The thing about Ruby to embrace out of the gate is how clean the syntax is and how a lot of Ruby style conventions are driven by that. For example, Ruby advises against methods with get and set in them, instead preferring things like name and name= for accessor and mutator methods.

Yes, you can have = at the end of a method name, just like you can have ? or !, each of which have taken to mean particular things.

It's also a given that the last operation you perform in a method is implicitly the return value, so there's no need for return.

Here's a simple refactoring of your code with that in mind:

class Athlete
  def number
    @number
  end

  def number=(value)
    @number = value
  end

  def name
    @name
  end

  def name=(value)
    @name = value
  end
end

You can reduce this even further since Ruby has a method that will generate these for you automatically called attr_accessor. You can also make your life a little easier by making an initialize method to populate these:

class Athlete
  attr_accessor :number
  attr_accessor :name

  def initialize(number, name)
    @number = number
    @name = name
  end
end

So to put this all together:

athletes = [ ]

File.readlines(input) do |line|
  number, name = line.chomp.split(/\s+/)

  athletes << Athlete.new(number, name)
end

A lot of Ruby code uses blocks to define operations that should happen. In this case readlines calls that block for each line read from the file. These lines include the \n newline at the end which chomp removes. << is a quick way to append something to an array.

Try to keep your variable and method names all lower-case as well. Capitals have significant meaning in Ruby, so jData should be jdata or j_data.

Update: To make this more debugger-friendly:

class Athlete
  def inspect
    "Athlete [%s] %s" % [ @number, @name ]
  end
end
Sign up to request clarification or add additional context in comments.

8 Comments

Okay so I understand all your code, how do I go about outputting the information and comparing between athletes. So like if I want to get the 2nd athlete (in my above 'dummy' file it'd be '19 Tanaka') what line am I using for that? Something like athletes[1]? I tried that and I get #<athlete:0x00000> there's more numbers which I'm guessing is what a pointer to where the data is saved
It's just a regular array, so athletes[1] returns the athlete at the index 1 position (second entry). This depends on there being two lines in your file, of course. If you're ever stumped, try using p athletes as a quick way to show debugging output on the console, or even better, use the irb tool to run small chunks of code and inspect the output.
I've added a little snippet there that defines inspect so your output looks more friendly. Those numbers are the object_id of the object in question, that's just the default inspect format.
Oh yes, I see when I use p athletes they all pop up, with the memory index first. So if I want to compare names to see if their last names are the same how would I address the first athlete (0) vs. the 2nd (1). I guess this is where I get confused about how to access the data. Is it something like athletes[0]@name or how do I address a single person? Eventually I want to make it so when someone types in a players number, it spits out their name. That's why I was wondering about addressing their names/numbers and all.
Don't think of it as memory index, it's just a unique object ID value. If you want to compare: athletes[0].name since you have an attr_accessor :name.
|
3

First off, you don't need to define explicit getters/setters. Something like this will do

class Athlete
  attr_accessor :name, :number

  def initialize(name, number)
    self.name = name
    self.number = number
  end
end

Or even shorter:

Athlete = Struct.new(:name, :number)

Then to create athletes:

athletes = File.foreach(file_path).map do |line|
  number, name = line.chomp.split(' ')
  Athlete.new(name, number)
end

You will now have an array full of Athletes.

1 Comment

@JohnBarr Notice that there was a missing : for number in the attr_accessor line. I fixed my post now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.