Ruby: Почему второй фрагмент кода, похожий на первый, выдает ошибку «неопределенный метод»? - PullRequest
0 голосов
/ 28 января 2019

Я не понимаю, как "dungeon.rb" работает нормально, в то время как "tarifs.rb" рушится с:

неопределенным методом 'full_description' для nil: NilClass (NoMethodError).

Обе части кода похожи.что отличается: имена классов, имена некоторых методов и их аргументы.

### OK piece -> dungeon.rb code

class Dungeon             
    attr_accessor :player 
    def initialize(player)
        @player = player  
        @rooms  = {}      
    end
    def add_room(reference, name, description, connections)
        @rooms[reference] = Room.new(reference, name, description, connections)
    end
    def start(location)            
        @player.location = location
        show_current_description    
    end
    def show_current_description
        puts "Location: " + find_room_in_dungeon(@player.location).full_description
    end
    def find_room_in_dungeon(reference)
        @rooms[reference]
    end
    def find_room_in_direction(direction)
        find_room_in_dungeon(@player.location).connections[direction]
    end  
    def go(direction)
        puts "\nYou go: " + direction.to_s
        @player.location = find_room_in_direction(direction)
        show_current_description
        puts "Where you want to go now? "
    end
end

class Player
    attr_accessor :name, :location
    def initialize(name)
        @name = name
    end
end

class Room
    attr_accessor :reference, :name, :description, :connections
    def initialize(reference, name, description, connections)
        @reference   = reference
        @name        = name
        @description = description
        @connections = connections
    end
    def full_description
        @name + "\n\n ** You are in " + @description
    end
end
#######---------------- Creating Player and Dungeon objects ------------------
puts         "Enter your name"
username   = gets.chomp
player     = Player.new(username)
my_dungeon = Dungeon.new(player)
#######---------------- Add rooms to the dungeon ----------------------
my_dungeon.add_room(:largecave,
        "Large Cave",
        "a large cavernous cave **",
        {:west  => :smallcave,
         :south => :grotto,
         :east  => :largecave })
my_dungeon.add_room(:smallcave,
    "Small Cave",
        "a small, claustrophobic cave **",
        {:west  => :smallcave, 
         :south => :grotto,
         :east  => :largecave })
my_dungeon.add_room(:grotto,
        "Wet Grotto",
        "a medium range grotto with water pool in center **",
        {:west  => :smallcave, 
         :south => :grotto,
         :east  => :largecave })

puts "Your name is: #{player.name}"
#######------------ Start the dungeon by placing the player in the large cave ------------------------
my_dungeon.start(:largecave)
#######------------- Player navigation ---------------------
ok_input = [:west, :east, :south, :exit]

loop do
    puts "Choose direction please: "
    input = gets.chomp.to_sym
    if ok_input.include?(input)
        my_dungeon.go(input)
    elsif ok_input.include?(input) == false
        puts "Wrong input!!! Allowed input: 'west', 'east', 'south' or 'exit' "
    end
    break if input == :exit
end


#### NOT OK piece -> tarifs.rb code

class Invest
   attr_accessor :user
       def initialize(user)
       @user   = user
       @tarifs = {}
   end

   def add_tarif(reference, tname, description, connections, procent, days)
       @tarifs[reference] = Tarif.new(reference, tname, description, connections, procent, days)
end

   def start(choosed_tarif)
       @user.choosed_tarif = choosed_tarif
       show_current_description
end

   def show_current_description
       puts "  Current tarif is: " +   find_tarif_in_tarifs(@user.choosed_tarif).full_description
   end

   def find_tarif_in_tarifs(reference)
       @tarifs[reference]
   end

   def find_tarif_in_direction(direction)
       find_tarif_in_tarifs(@user.choosed_tarif).connections[direction]
   end

   def go(direction)
       puts "\nYou choosed: " + direction.to_s
       @user.choosed_tarif = find_tarif_in_direction(direction)
       show_current_description
   end
end

class User
   attr_accessor :uname, :choosed_tarif        
   def initialize(uname)
       @uname = uname
   end
end

class Tarif
   attr_accessor :reference, :tname, :description, :connections, :procent, :days
   def initialize(reference, tname, description, connections, procent, days)
       @reference   = reference
       @tname       = tname
       @description = description
       @connections = connections
       @procent     = procent
       @days        = days
   end

   def full_description
      @tname + "\n  " + @description
   end
end

#######-------- Creating User and Invest objects ----------
puts        "Enter your name"
uname    =  gets.chomp
user     =  User.new(uname)
my_tarif =  Invest.new(user)

#######-------- Adding tariffs to the Invest --------------
my_tarif.add_tarif(:start,
                   "Start",
                   "Start tarif 2% daily for 3 days in total",
                   {:first  => :start,
                   :second => :business,
                   :third  => :profi },
                   2,
                   3)
my_tarif.add_tarif(:business,
                   "Business",
                   "Business tarif 3% daily for 5 days in total",
                   {:first  => :start,
                    :second => :business,
                    :third  => :profi },
                    3,
                    5)
my_tarif.add_tarif(:profi,
                   "Profi",
                   "Profi tarif 4% daily for 10 days in total",
                   {:first  => :start,
                    :second => :business,
                    :third  => :profi },
                    4,
                    10)

#######-------- Autostarts with first tarif --------------
my_tarif.start(:business)

#######-------- Tarif navigation --------------
ok_input = [:start, :business, :profi, :exit] 
puts "Choose your tarif: "
input    = gets.chomp.to_sym

if       input == :start
         my_tarif.go(input)
   elsif input == :business
         my_tarif.go(input)
   elsif input == :profi
         my_tarif.go(input)
   else  puts "Please input 'start', 'business' or 'profi' !!!"
end

Код tarifs.rb должен позволять перемещаться в tarifs.rb - так же, как код dungeon.rb позволяет перемещаться по комнатам.Между тем, вывод tarifs.rb показывает следующее:

tarifs.rb: 22: в show_current_description ': неопределенное methodfull_description' для nil: NilClass (NoMethodError) из tarifs.rb: 36: in go 'из тарифов.rb: 111: в '

1 Ответ

0 голосов
/ 28 января 2019

Вы вызываете метод full_description на nil.Проблема заключается в следующих методах:

   def show_current_description
       puts "  Current tarif is: " +   find_tarif_in_tarifs(@user.choosed_tarif).full_description
   end

   def find_tarif_in_tarifs(reference)
       @tarifs[reference]
   end

Вы будете вызывать full_description с результатом find_tarif_in_tarifs(@user.choosed_tarif).т.е. на @tarifs[@user.choosed_tarif].Очевидно, что для этого пользователя в хеше @tarifs нет зарегистрированного тарифа.

Вы должны обработать этот случай - либо проверяя, является ли возвращаемое значение не ноль, def show_current_description, если find_tarif_in_tarifs (@ user.choposed_tarif) ставит "Текущий тариф: "+ find_tarif_in_tarifs (@ user.choposed_tarif) .full_description else ставит" Тариф не найден "в конце

или возвращая значение по умолчанию из find_tarif_in_tarifs

   def show_current_description
     @tarifs.fetch(references, default_tariff) #(you need to define default_tariff method)
   end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...