15

I am not a ruby expert and this is giving me trouble. But how Would I go about creating an array of objects/classes in ruby? How would initialize it/declare it? Thanks in advance for the help.

This is my class, and I want to create an array of it:

class DVD
  attr_accessor :title, :category, :runTime, :year, :price

  def initialize()
    @title = title
    @category = category
    @runTime = runTime
    @year = year
    @price = price
  end
end
Peter Brown
  • 50,956
  • 18
  • 113
  • 146
Chris Cruz
  • 171
  • 1
  • 1
  • 3

3 Answers3

20

Ruby is duck typed (dynamic typing) And almost everything is an object, so you can just add any object to an array. For example:

[DVD.new, DVD.new]

will create an array with 2 DVDs in it.

a = []
a << DVD.new

will add the DVD to the array. Check the Ruby API for the full list of array functions.

Btw, if you want to keep a list of all the DVD instances in the DVD class you can do this with a class variable, and add it to that array when you create a new DVD object.

class DVD
  @@array = Array.new
  attr_accessor :title, :category, :runTime, :year, :price 

  def self.all_instances
    @@array
  end

  def initialize()
    @title = title
    @category = category
    @runTime = runTime
    @year = year
    @price = price
    @@array << self
  end
end

now if you do

DVD.new

you can get the list of all the DVDs you have created so far:

DVD.all_instances
jake
  • 1,661
  • 1
  • 21
  • 30
rik.vanmechelen
  • 1,904
  • 17
  • 24
  • 1
    Not almost everything is an object, *everything is an object*. Also, in general, class instance variables should be preferred over class variables. – Andrew Marshall Jan 26 '13 at 02:06
  • 1
    Except really blocks are objects: `def f &block; block; end; f {}`. Which returns, well, *an object*. – Andrew Marshall Jan 26 '13 at 03:06
  • 1
    @AndrewMarshall yes, like that they are converted to a proc, but when you have to yield for it, it is not an object :) therefore not everything, but almost everything is an object. – rik.vanmechelen Jan 26 '13 at 10:13
9

two_DVD = Array.new(2){DVD.new}

Fanda
  • 325
  • 5
  • 14
  • 2
    The first time I tried this: Array.new(2, DVD.new) and this ended up creating 2 copies of the same object. Then I found your answer "Array.new(2){DVD.new}" and found it to create 2 unique objects, which is what I needed. Thank you! – JasonArg123 Nov 22 '18 at 01:03
7

In order to create an array of objects in Ruby:

  1. Create the array and bind it to a name:

    array = []
    
  2. Add your objects to it:

    array << DVD.new << DVD.new
    

You can add any object to an array, at any time.

If you wish to have access to every instance of the DVD class, then you can rely on ObjectSpace:

class << DVD
  def all
    ObjectSpace.each_object(self).entries
  end
end

dvds = DVD.all

By the way, the instance variables are not being initialized correctly.

The following method call:

attr_accessor :title, :category, :run_time, :year, :price

Automatically creates attribute/attribute= instance methods to get and set the value of the instance variables.

The initialize method, as defined:

def initialize
  @title = title
  @category = category
  @run_time = run_time
  @year = year
  @price = price
end

Sets the instance variables, despite taking no arguments. What effectively happens is:

  1. The attribute reader method is called
  2. It reads the unset variable
  3. It returns nil
  4. nil becomes the value of the variable

What you want to do is pass the values of the variables to the initialize method:

def initialize(title, category, run_time, year, price)
  # local variables shadow the reader methods

  @title = title
  @category = category
  @run_time = run_time
  @year = year
  @price = price
end

DVD.new 'Title', :action, 90, 2006, 19.99

Also, if the only required attribute is the DVD's title then you can do it this way:

def initialize(title, attributes = {})
  @title = title

  @category = attributes[:category]
  @run_time = attributes[:run_time]
  @year = attributes[:year]
  @price = attributes[:price]
end

DVD.new 'Second'
DVD.new 'Third', price: 29.99, year: 2011
Matheus Moreira
  • 17,106
  • 3
  • 68
  • 107