Dynamic instances of a class

Hi everyone, i'm really new to ruby and i'm trying to solve the next
piece of code:

require 'csv'

class Motorcycle
  attr_reader :name, :weight
  @@count = 0

  def self.find (name)
    found = nil
    ObjectSpace.each_object(Motorcycle) { |o|
      found = o if o.name == name
    }
    found
  end

  #Dynamically create instances of Motrocycle
  def self.create
  PARAMS = File.read('motorcycles.csv').split("\n").map { |line|
line.split(',') }
  end

  def initialize (name, weight)
  @name = name
  @weight = weight
  self.class.count += 1
  end

  def self.count
  @@count
  end

  def available_colors
  end

  def has_abs?
  end
end

My code must be able to get trough this test:

#Test that must pass

describe Motorcycle do
  describe "loading the motorcycle list" do
    it "should load 2 motorcycles from the CSV" do
      Motorcycle.count.should == 2
    end
  end

  describe "finding a motorcycle by name" do
    it "should return an instance of the Motorcycle class" do
      Motorcycle.find("1200 RT").should be_a Motorcycle
    end
  end

  describe "#weight" do
    it "should have a weight of 800 pounds for the 1200 RT" do
      Motorcycle.find("1200 RT").weight.should == '800 pounds'
    end

    it "should have a weight of 500 pounds for the 600 GS" do
      Motorcycle.find("600 GS").weight.should == '500 pounds'
    end
  end

  describe "#available colors" do
    it "should find 'red' and 'black' as available colors for the BMW
1200 RT" do
      Motorcycle.find("1200 RT").available_colors.should == [ 'red',
'black' ]
    end

    it "should find 'green' and 'blue' as available colors for the BMW
600 GS" do
      Motorcycle.find("600 GS").available_colors.should == [ 'green',
'blue' ]
    end
  end

  describe "#has_abs?" do
    it "should be true for a motorcycle that appears in
abs_motorcycles.txt" do
      Motorcycle.find("1200 RT").has_abs?.should be_true
    end

    it "should be false for a motorcycle that does not appear in
abs_motorcycles.txt" do
      Motorcycle.find("600 GS").has_abs?.should be_false
    end
  end
end

Problem is i don't know much about ruby. i already got over the fact of
getting a count of how many instances of the class have been created,
also on how to find a instance of the class by its name, but don't know
how to create the instances of said class dynamically (via the create
method i'm trying to write), i know that the code line inside the create
method gives me an array that contains the information extracted from
the file "motrocycle.csv", first row contains the headers for each
column (which i'm not sure if its really useful), first column contains
the name that each instance of motorcycle should have, this is where my
big problem is located, not sure how to do that, so please, if anyone
could help me out i would really appreciate it :D.

Thanks in advance, its really urgent.

···

--
Posted via http://www.ruby-forum.com/.

I'm not an expert, but your question I can answer. Woohoo!

You can create instances with new(). E.g., given your code as shown:

    aMotorCycle = Motorcycle.new("blahblah", "800 pounds")

This invokes your 'init' method.

But you're trying to do something a little trickier, which is (I think)
to create many motorcycles at once. You can do that with a class method
that returns an array of motorcycles:

   def Motorcycle.getMany(filename)
      File.new(filename).readlines.map{ |line|
         Motorcycle.new( line.split( '.' ) )
      }
   end

This could be invoked thus:

   manyMotorcycles = Motorcycle.getMany('motorcycles.csv')

(There are a few more improvements you could make to your code but I
won't clutter this answer with them.)

Good luck, and have fun with Ruby!

ps: I stumbled on your question while checking for an answer to my Rake
question: http://www.ruby-forum.com/topic/3130799#new
No answers yet. Anyone with Rake chops out there? Hello?

···

--
Posted via http://www.ruby-forum.com/.

Oops, I didn't take into account the format of your data file, in which
the first line is not data but headings. So here's a refinement:

   def Motorcycle.getMany(filename)
      File.new(filename).readlines[1..-1].map{ |line|
         Motorcycle.new( line.split( ',' ) )
      }
   end

···

--
Posted via http://www.ruby-forum.com/.

For some estrange reason it wont let me edit, but i'll share my results.

I give it a tray but it wont work as my initialize method receives 2
parameters and it seems that "line.split(',')" is considered a single
parameter, so i figure i will have to try some way else, or maybe ¿is it
possible to assign the line.split value to 2 different variables at the
same time after the "map{" and then create the new instance with
"Motorcycle.new(var1,var2)"?.

···

--
Posted via http://www.ruby-forum.com/.

Oops again! This should work better:

    Motorcycle.new( *line.split( ',' ) )

line.split(',') is a single arg that is an array.
The * turns the array into a list of args.

Also, wrt your earlier reply, note that [1..-1] gets the 2nd thru last
elements of an array. The first thru last would be [0..-1].

···

--
Posted via http://www.ruby-forum.com/.

OK, hate to multi-post, but wanted to let you know that i made it, is
not really elegant, i wish there was a better way to do it, but at least
i (kind of) get a solution for the main problem on this post.

Here is the code.

require 'csv'

class Motorcycle
  attr_reader :name, :weight
  @@count = 0

  def self.find (name)
    found = nil
    ObjectSpace.each_object(Motorcycle) { |o|
      found = o if o.name == name
    }
    return found
  end

  #Dynamically create instances of Motrocycle
  def self.create
  File.new('motorcycles.csv').readlines[1..-1].map{ |line|
    first, *rest = line.split(/,/)
    Motorcycle.new( first, rest )
    }
  end

  def initialize (name, weight)
  @name = name
  @weight = weight
  self.class.count += 1
  end

  def self.count
  return @@count
  end

  def self.count=( count )
  @@count = count
  end

  def available_colors
  end

  def has_abs?
  end
end

Is there any way to do it better, like, ¿ what is i didn't have 2
columns but multiple columns? (i was thinking of creating a array with
the values and then using 2 for loops to retrieve each value, but that
would have been really stupid i believe).

···

--
Posted via http://www.ruby-forum.com/.

La Wi wrote in post #1034939:

Oops, I didn't take into account the format of your data file, in which
the first line is not data but headings. So here's a refinement:

   def Motorcycle.getMany(filename)
      File.new(filename).readlines[1..-1].map{ |line|
         Motorcycle.new( line.split( ',' ) )
      }
   end

wow thanks this really is light in the empty void of my ignorance, i'll
give it a try now, im guessing that if i change the line
".readlines[1..-1]" for something like ".readlines[2..-1]" it will start
on the second line of my file, well any way i'll try it out now and
share my results.

PD: About your problem, i really can't help you there, not really and
expert on that regard but really wish you luck, if i stumble upon
something related i'll let you know :D.

···

--
Posted via http://www.ruby-forum.com/\.

Yes, use the CSV library you've required (but never used) to parse
the file -- that's what it's for :slight_smile:

···

On Sat, Dec 3, 2011 at 7:05 PM, Andres M. <andres.mrad@gmail.com> wrote:

require 'csv'

Is there any way to do it better, like, ¿ what is i didn't have 2
columns but multiple columns?

--
Hassan Schroeder ------------------------ hassan.schroeder@gmail.com

twitter: @hassan

Be careful here, because you are only referring to your Motorcycle
instances via ObjectSpace if ruby's garbage collection runs it will
think that none of those objects are used anymore and would destroy
them. ObjectSpace isn't something you want to be using as your
'storage' system (think of it more as a debugging tool).

Fred

···

On Dec 4, 3:05 am, "Andres M." <andres.m...@gmail.com> wrote:

OK, hate to multi-post, but wanted to let you know that i made it, is
not really elegant, i wish there was a better way to do it, but at least
i (kind of) get a solution for the main problem on this post.

Here is the code.

require 'csv'

class Motorcycle
attr_reader :name, :weight
@@count = 0

def self.find (name)
found = nil
ObjectSpace.each_object(Motorcycle) { |o|
found = o if o.name == name
}
return found
end

Hassan Schroeder wrote in post #1034978:

···

On Sat, Dec 3, 2011 at 7:05 PM, Andres M. <andres.mrad@gmail.com> wrote:

require 'csv'

Is there any way to do it better, like, what is i didn't have 2
columns but multiple columns?

Yes, use the CSV library you've required (but never used) to parse
the file -- that's what it's for :slight_smile:

Ok, i really have no experience, and must say that the library was there
when i started, i didn't include it :confused: nor did i dig too much into it, i
thought maybe that was required for something(just like in C and C++
where you have a bunch of libraries with each new file).

--
Posted via http://www.ruby-forum.com/\.