Search code examples
rubyyaml

t shows me Psych::DisallowedClass when I try to deserialise a yaml file


def start_game
        game = true
        loop do
            print "number of chances remaining: #{@chances} \n"
            print "#{@dash.join('')} \n"
            puts "type your letters to play(or type 'save' to save the game at any point)"
            check_letter = gets.chomp.downcase
        
            if check_letter == 'save'
                save_file
            elsif @secret_word.include?(check_letter)
                array_of_guess_word =  @secret_word.split('')
                arr2 = array_of_guess_word.each_index.select {|x| array_of_guess_word[x] == check_letter}
                arr2.each do |idx|
                    @dash[idx] = check_letter 
                end
            else  
                @guessed_letter << check_letter
            end
            
            print "Letters not inlcuded: #{@guessed_letter} \n\n"
            print "Yes! the word was: #{@secret_word} \n You won congratulations #{@name}" if @dash.eql?(array_of_guess_word)
            break if @dash.eql?(array_of_guess_word)|| @chances == 0
            @chances -= 1
        end
    end

     def load_file
       if !Dir.exist?('./saved_games/')
        loop do 
         puts '\nNo saved games!'
         break if user_input == '1'
        end
       else
        loaded_game =
         File.open("./saved_games/#{load_file_name}.yml", 'r') do |file|
            YAML.load(file)
            end
            loaded_game.start_game
        end
    end

    def load_file_name
        saved_games = Dir.glob('saved_games/*').map {|game| game.split('/').last.split('.yml').first}
        file_count = saved_games.count 
        loop do 
            puts "Enter a number to load the game: "
            saved_games.each_with_index {|game , idx| puts "#{idx + 1} , #{game}"}
            file_number = gets.chomp.strip
            if /\A[0-9]+\Z/.match?(file_number) &&  file_number.to_i <= file_count
            return saved_games[file_number.to_i - 1]
            end
        puts "\nInvalid input.\n\n"
        end
    end 

when I try to load the file I get this error saying psych::DisallowedClass. I just can't deserialise my yaml code

I want where I went wrong exactly. I think is it because of the instance variables I used in the code. I'm new to serialization


Solution

  • By default, Psych (the library used by Ruby to handle YAML) only allows a limited list of classes (TrueClass, FalseClass, NilClass, Integer, Float, String, Array, and Hash) to be deserialized for security reasons.

    When you want to allow other classes (like in your example your custom Hangman class) to be deserialized from your YAML file, then you have to allow those classes explicitly:

    YAML.load_file(file_name, permitted_classes: [Hangman])
    

    I suggest changing your load_file method like this:

    def load_file
      if Dir.exist?('./saved_games/')
        file_name = "./saved_games/#{load_file_name}.yml"
    
        loaded_game = YAML.load_file(file_name, permitted_classes: [Hangman])
        loaded_game.start_game
      else
        loop do 
          puts "\nNo saved games!"
          break if user_input == '1'
        end
      end
    end