-1

I have a few syntax errors on my program that are really bothering me. I can't seem to figure out how to fix them as I am new to ruby. The first error is on the title, I have a few more I'm sure. The purpose of the program is to create cars with make, model, and year and have user input how many cars they want then display all of them at the end.

Can someone point me to the right direction?

Here is my code:

class Car

def initialize(make, model, year)
 @make = make
 @model = model
 @year = year

end

print "How many cars do you want to create? "
array_of_cars = Array.new  
num_cars = gets.to_i

c = car.new

 for i in 1..num_cars 
    end

puts
print "Enter make for car #{i}: "
make = gets.chomp

print "Enter model for car #{i}: "
model = gets.chomp

print "Enter year for car #{i}: "
year = gets.to_i

c.set_make(make)
c.set_model(model)
c.set_year(year)

array_of_cars << c 
 end 

 puts
 puts "You have the following cars: " 

 for car in array_of_cars 
   puts "#{car.get_year} #{car.get_make} #{car.get_model}" 
  end
Lily Rubio
  • 33
  • 4

3 Answers3

3

In ruby, class names are constants, so should start with a capital letter, as in class Car. When creating a new object of that class, you call new on the class itself. So you would change car.new into Car.new.

You will also need to define your set_* and get_* methods inside the class, but since this is a common pattern, ruby has attr_accessor available. See this answer for a full explanation of attr_accessor.

Tom
  • 412
  • 2
  • 9
2

Consider that your Car does not do anything, it contains only data and has no methods. When this happens, consider making it a Struct instead of a class. A Struct generates a reader and writer method automatically without even specifying attr_reader.

Car = Struct.new(:make, :model, :year)
array_of_cars = Array.new

while true
    puts
    print "Enter make for car ('x' to exit): "
    make = gets.chomp
    break if make == 'x'

    print "Enter model for car: "
    model = gets.chomp

    print "Enter year for car: "
    year = gets.to_i

    array_of_cars << Car.new(make, model, year)
end

puts
puts 'You have the following cars:' # sorted by year for fun

array_of_cars.sort_by{ | car | car.year }.each do | car |
    puts "#{car.year} #{car.make} #{car.model}"
end
Tom
  • 412
  • 2
  • 9
1

A few pieces of advice.

Run Ruby with the -w option :

$ ruby -w cars.rb 
cars.rb:17: warning: mismatched indentations at 'end' with 'for' at 16
cars.rb:34: warning: mismatched indentations at 'end' with 'class' at 1
cars.rb:41: warning: mismatched indentations at 'end' with 'for' at 39

and eliminate the cause of warnings.

$ ruby -w cars.rb 
How many cars do you want to create? 2
cars.rb:2:in `initialize': wrong number of arguments (given 0, expected 3) (ArgumentError)
    from cars.rb:13:in `new'
    from cars.rb:13:in `<main>'

new calls initialize, so new must have the same number of arguments as parameters in initialize. Hence a car can be created only after you have asked all the information.

Don't work in the class. As written, your code is executed when Ruby reads the class definition. For this exercise, you can leave it in the main level outside the class definition, or put it into a method.

 for i in 1..num_cars 
 end

This loop is empty and does nothing. And prefer powerful iterators instead of this C, Perl, Java style (for, while, etc).

I define strings with apostrophes and keep double quotes when interpolation is needed (even if it's a question of nano seconds and personal choice). See here and there.

If you want to be comfortable with Ruby programming, I recommend The Pickaxe.

There are many ways of doing things in Ruby. The following is one solution.

class Car
    attr_reader :make, :model, :year

    def initialize(make, model, year)
        @make  = make
        @model = model
        @year  = year
    end

    def self.make_car # class method (more precisely : singleton method)
        print 'How many cars do you want to create? '
        array_of_cars = Array.new
        num_cars = gets.to_i

        num_cars.times do | i |
            real_index = i + 1
            puts
            print "Enter make for car #{real_index}: "
            make = gets.chomp

            print "Enter model for car #{real_index}: "
            model = gets.chomp

            print "Enter year for car #{real_index}: "
            year = gets.to_i

=begin
            c = Car.new(make, model, year)
            array_of_cars << c 
=end
            # some will tell you to avoid unnecessary variables ...
            array_of_cars << Car.new(make, model, year)
        end

        puts
        puts 'You have the following cars:' # sorted by year for fun

        array_of_cars.sort_by{ | car | car.year }.each do | car |
            puts "#{car.year} #{car.make} #{car.model}"
        end
    end
end # class Car

Car.make_car
BernardK
  • 3,674
  • 2
  • 15
  • 10
  • Thank you for your explanation and helpful links! I will definitely check them out as I need all the help I can get! – Lily Rubio Oct 28 '17 at 04:07
  • A singleton method only exists for the specific object that is created. They can be different and mutate themselves for each instance of the class. If you don't need this functionality, singletons are wasteful because they create a copy of the singleton method every time you instantiate it. – Tom Oct 28 '17 at 07:54
  • @Tom _A singleton method only exists ..._ Right. _singletons are wasteful because they create a copy_ Where did you find that ? As far as I know, only `alias` and `alias_method` create a copy. Singleton/class methods, like instance methods, are not copied for each instance. They are part of the methods list. Objects have a pointer to their class, hence to the unique list of methods. See [What does self mean ?](https://stackoverflow.com/questions/13706373/what-does-def-self-function-name-mean/13709911#13709911). – BernardK Oct 28 '17 at 09:38
  • You're right, I had it backwards. It's actually more efficient. You actually want a singleton if it is class-level (or Module-level) functionality that does not vary between instances, especially if you do not need the results back. – Tom Oct 28 '17 at 20:54