Avatar

Hi! Ive posted before about some problems Im receiving when I run my program from the terminal. I have 5 menu options. 1 is to checkin. There I manage to go through the steps for a check_in but when completed it gives me a undefined method `generateParkingLot' for #<Camping:0x10030af38> (NoMethodError). When I choose the second option which is check_out it gives me this error: ./ruby_camping.rb:110:in `check_out': undefined method `chomp_to_i' for "1\n":String (NoMethodError)
from ./ruby_camping.rb:69:in `do_action'
from ./ruby_camping.rb:49:in `menu'
When i choose the third option i only get nil. For the fourth option I get: ./ruby_camping.rb:73:in `do_action': undefined method `all_guests' for nil:NilClass (NoMethodError)
from ./ruby_camping.rb:49:in `menu'
from main.rb:18
So I dont know what to do. Ive tried googling talking to friends for several day and cant seem to find the answer. Please can anyone help. I have pasted here the full code and in the main class aswell the error i get when executing it through TextMate which says that i have not initialized the instance variable @parking_lots. I am getting quite desperate cos I have past the deadline for this project for my summer course. Thanks!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
require 'ruby_camping'
require 'camping_guests'

=begin 
	Mainclass for program: Creates a camping and
       starts the loops for the menu.

=end
class Main	
	
	if __FILE__ == $0	
		$camping = Camping.new(@current_guests, @all_guests, @parking_lots) # skapa en ny camping  # !> instance variable @parking_lots not initialized
		puts "\n"
		puts "Välkommen till Ruby Camping!"

		
		# loopa igenom menyn
		while (true)
			Menu.menu
		end
	end   
end


require 'parking_lot' 

class Camping 
	
	attr_accessor :current_guests, :parking_lots, :all_guests
	
	def initialize(current_guests, parking_lots, all_guests)
	  
	   @current_guests = Array.new(32)

  	 # initiera husvagnsplatserna
  	 @parking_lots = Array.new(32)
  	 32.times do |nr|
  		 @parking_lots[nr] = Parking_Lot.new(nr)
  	       
  	end
		
		defaultGuests = Array[ 
		Guest.new("Logan", "Tokyo", "07484822",1, @parking_lots[0]), 
		Guest.new("Scott", 	"Chicago", "8908332", 2, @parking_lots[1]),
	  Guest.new("Hank", 	"Boston", "908490590", 3, @parking_lots[2]),
	  Guest.new("Jean", "Detroit", "48058221", 4, @parking_lots[3]),
	  Guest.new("Charles",	"Washington DC", "019204822",5, @parking_lots[4])
    ]
    
    @all_guests = []    
		 
	  defaultGuests.each do |guest|
			@current_guests[guest.plot.nr] = guest
			@all_guests.push(guest)
		end                            
  end
end  

  # Returnerar en strängrepresentation av gästlistan, dvs to_s från Guest-klassen.
	# Om en plats är ledig skrivs texten "Ledig" ut.
	def to_s
		# skapa en tom sträng som fylls på vidare
		list = "Husvagnsgäster\n"
		
		# loopa från 1 till 32
		(1..32).each do |n|
			# översätt positionen till 0-baserad array och kolla om det finns 
			# någon gäst registrerad på positionen, och i så fall lägg till 
			# texten i list
			if (!@current_guests[n-1].nil?)
				list += @current_guests[n-1].to_s
			else
				# annars, lägg till texten "Ledig"
				list += n.to_s + ": Ledig\n"
			end
		return list
	end
	
  # Naiv lösning till att slumpa fram en ledig parkeringsplats. Returnerar en
 	# ledig plats (nummer mellan 1-32).
 	def generateParkingLot
 		# slumpa ett tal mellan 1 och 32
 		randomNr = 1+rand(32)
 		# finns det en gäst på den (0-baserade) positionen?
   		if (!@current_guests[randomNr-1].nil?)
   			# isåfall, generera en ny siffra
   			generateParkingLot
   		else
   			# returnera den genererade siffran
   			return randomNr
   		end
 	end
end


require 'date' #inkluderar date klassen
require 'camping_guests' #inkluderar filen med alla gäster
require 'parking_lot'

class Guest
  
  attr_accessor :firstname, :lastname, :address, :phone, :departure
  attr_reader :plot, :arrived
  
  # metod för gästen
  def initialize (firstName, lastName, address, phone, plot)  
    @firstName = firstName
    @lastName = lastName
    @address = address
    @phone = phone
    @arrived = Date.today.to_s    # dagens datum som en sträng
    @plot = plot           
  end

  
  # konverterar den inskrivna registreringen till en sträng som jag konkatinerat
  def to_s 
    return 	"Dina uppgifter: " +
				"\n\tFullständigt namn: #{@firstName} #{@lastName}" +
				"\n\tAdress: #{@address}" +
				"\n\tTelefon: #{@phone}" +
				"\n\tAnkomst: #{@arrived}" +
				"\n\tPlats: #{@plot}" +
				"\n\tElmätaren: #{@cabinet} kWh" +
				 "\n\tTack välkommen åter!"
	    end 
end

class Menu 

def self.menu  
  		puts "---------------------------"
      puts "      Meny"
      puts "  1. Incheckning"
      puts "  2. Utcheckning"
      puts "  3. Lista aktuella gäster"
      puts "  4. Lista samtliga gäster"
      puts "  5. Avsluta\n"
      puts ""
      puts " Vad vill du göra?"
      puts "---------------------------"
      print ": "
      action = get_input
  		do_action(action)
    end

    # Hämtar menyval och returnerar valt alternativ. 
    def self.get_input  
      input = gets.chomp.to_i

     while input > 5 || input < 1 do
         puts "Du valde nog fel, försök igen."
         input = gets.chomp.to_i
      end 
      return input
    end
    
   def self.do_action(action)
     # utför händelse baserat på valet
      case action
         when 1:
            check_in
         when 2:
            check_out
         when 3:
           puts @camping
          when 4:
           puts @camping.all_guests
          when 5:
           puts "Nu lämnar du campingen, välkommen åter!"
           exit    
         end
      end


=begin
  användaren kan checka in och här frågas efter uppgifter som sedan skapar ett
  Guest-objekt. Om det redan skapats en kommer denna att skrivas över.
  obs förslag på upplägget fick jag efter feedback på forumet stackoverflow
  där jag förklarade mitt problem och en kom med en lösning baserat på vad jag beskrivit
=end
    def self.check_in
        puts " Var god skriv in för- och efternamn: "
        name = gets.chomp.split(" ")  # detta splittar strängen i för -och efternamn
        puts "Skriv in adress: "
        address = gets.chomp
        puts "Skriv in ditt telefonnummer: "
        phone = gets.chomp
        puts "Ange datum för din ankomst"
        arrived = gets.chomp
        
        # hämta ledig plats och låta gästens plats peka på den
    		newPLot = $camping.generateParkingLot
    		newGuest = Guest.new(name, address, phone, arrival, $camping.parking_lots[newPLot-1])
    		$camping.current_guests[newPLot-1] = newGuest
    		$camping.all_guests.push(newGuest)	# lägg till gästen i historiken

    		puts "Registreringen lyckades. Du har fått husvagnsplats " + newPLot.to_s + "."
    	end                          

# Checkar ut användaren. Om det inte finns en användare registrerad, skrivs
# ett felmeddelande ut istället.
  def self.check_out 
    puts "Välkommen till utcheckningen!\nFör att checka ut någon ange campingplats:"
    plot = gets.chomp_to_i
    guest = $camping.current_guests[plot-1] 
    
    if (guest.nil? || plot < 1)	
			puts "Det finns ingen gäst på den positionen eller så har du angett en ogiltig position."
		else
			puts "Du vill checka ut " + guest.name + "."
			puts "Ange utcheckningsdatum: "
			departureDate = gets.chomp.to_i
			guest.departure = departureDate
			guestStayedDays = departureDate - guest.arrival		# antal dygn gästen har stannat 
			guest.plot.increase(guestStayedDays) 				# ökar elmätaren
			puts guest											# skriv ut gästen
			$camping.current_guests[plot-1] = nil				# töm platsen
		end
	end
 end


=begin
	Representerar en husvagnsplats. Varje husvagnsplats har ett nummer och en
	elmätare.
=end
class Parking_Lot
	
	attr_accessor :nr
	attr_reader :electricity_meter
	
	# Initierar en ny husvagnsplats med numret nr och en elmätare mellan
	# 2000 och 4000.
	def initialize (nr)
		@nr = nr
		@electricity_meter = 4000-rand(2000)	# slumpa tal mellan 2000 och 4000
	end
	
	# Ökar elmätaren för användning med en slumpmässig mängd mellan 
	# 10-80 kWh per dygn.
	def increase_meter(days)
		generatedUse = (10+rand(70))*days
		puts "Ökar elmätaren med " + generatedUse.to_s + " kWh."
		@electricity_meter += generatedUse
	end
	
	# Returnerar en strängrepresentation av husvagnsplatsen.
	def to_s
		"
	Husvagnsplats #{@nr+1}:
	Elmätare #{@electricity_meter} kWh
		"
	end	
end 
 


Refactorings

No refactoring yet !

Avatar

steved

July 27, 2010, July 27, 2010 15:48, permalink

No rating. Login to rate!

(Code as presented won't run; by removing some 'require's and reordering the class definition I got it to run)

1. I suspect English isn't your first language (nor is Ruby!) but it is key to learn how to read Ruby error messages.
2. undefined method `generateParkingLot' for #<Camping:0x10030af38> means just what is says. The Camping class has no such message. You defined generateParkinLot (and to_s) outside the Camping class ("end" statement on line 57 needs to be below the generateParkingLot method).
3. Got a little further and found Guests has an "arrived" attribute, but you reference an "arrival" attribute.

This should get you making progress.

Avatar

bob

July 27, 2010, July 27, 2010 16:43, permalink

No rating. Login to rate!

it's very simple. "@camping" is nil (it's never set in the Menu class at all). in fact, I don't think you should be using instance variables in a class method

Avatar

tragicdancer.myopenid.com

July 27, 2010, July 27, 2010 17:47, permalink

No rating. Login to rate!

Well thank you steved. And yes you are correct. English is not my first language, nor is Ruby(my first course in it, and it has only been a month). I really appreciate your help. You mentioned that you removed some of the 'require's' and reorded the class definition? In what way did you reorder it and which requires did u leave out? I know its really important to learn the error messages and thats what I have tried to do, trust me:) Thank you for your guidance:)

Avatar

steved

July 28, 2010, July 28, 2010 05:45, permalink

No rating. Login to rate!

It looks like your classes were in originally in separate source files (which you didn't provide) and you pasted the class definitions in what you posted. Code like "require 'ruby_camping'" is going to fail if ruby_camping.rb isn't in the load path. And you didn't provide 'ruby_camping.rb'. Try running what you posted in a directory with no other files and you'll get a bunch of error messages (constant not found if I recall correctly).

Avatar

tragicdancer.myopenid.com

July 28, 2010, July 28, 2010 08:07, permalink

No rating. Login to rate!

That is true. They are in different source files. Though I thought that when you require another file you just "need" to put require 'ruby_camping' and not the 'rb' at the end as well? When I posted the code I just pasted all the code and I thought that the 'require's' at the top of the classes were self explanatory and indicated that they were in separate source files. My mistake. So that means that I do have to put require 'ruby_camping.rb' and not require 'ruby_camping' right?! Once again thank you steved!!

Avatar

steved

July 28, 2010, July 28, 2010 15:33, permalink

No rating. Login to rate!

You don't nee the .rb extension. But my point is that you posted a script with several require <filename> but rather than including the various <filename>'s you had inlined the code in the script you provided. So when I ran the script the require statements failed. I could remove the requires because the class definitions were in the script.

Your refactoring





Format Copy from initial code

or Cancel