Search code examples
rubytext-based

How to dump a class into another class to create a save state


I have a small class which is for a character and we can assign to it from outside the class.

I need to know how I can dump all the information in that class into another that can be used to create a YAML file.

require "yaml"

module Save
  filename = "data.yaml"
  character = []
  sex = []
  race = []
  stats = [Str=[], Dex=[], Con=[], Int=[], Wis=[], Cha=[]]
  inventory = []
  saving_throws = [fortitude=[], reflex=[], will=[]]
  #Armor Class, Flat footed Armor Class, and Touch armor Class
  armor_class = [ac=[], fac=[], tac=[]]
  armor_worn = [head=[], eyes=[], neck=[], shoulders=[], body=[], torso=[],     arms_wrists=[], hands=[], ring1=[], ring2=[], waist=[], feet=[]] 
  money = []
  god = []
  speciality_school = [] #wizard
  companion = [] #also used for familirs and psicrystals
  skills = []
  class_race_traits = []
  feats = []
  languages = []

  program_data = {
    character: character,
    sex: sex,
    race: race,
    stats: stats,
    inventory: inventory,
    saving_throws: saving_throws,
    armor_class: armor_class,
    armor_worn: armor_worn,
    mony: money,
    god: god,
    speciality_school: speciality_school,
    companion: companion,
    skills: skills,
    class_race_traits: class_race_traits,
    feats: feats,
    languages: languages
  }

  File.write filename, YAML.dump(program_data)
end

This is the code I want to use to obtain the user content from the player:

class Character
  attr_reader :name, :race, :description

  def initialize (name, race, description)
    @name = name
    @race = race
    @description = description  
  end
end

def prompt
  print "Enter Command >"
end

puts "What is your name?"
prompt; name = gets.chomp.downcase

puts "What is your race?"
prompt; race = gets.chomp.downcase

puts "What do you look like?"
prompt; desc = gets.chomp.downcase

player_one = Character.new(name, race, desc)
puts player_one

I'm stuck on how to load it back and refill the character content to make it continue where the player left off.


Solution

  • Meditate on this bit of fictional code:

    require 'yaml'
    
    SAVED_STATE_FILE = 'saved_state.yaml'
    
    class User
      def initialize(name=nil, address=nil)
        @name = name
        @address = address
      end
    
      def to_h
        {
          'name'    => @name,
          'address' => @address
        }
      end
    
      def save
        File.write(SAVED_STATE_FILE, self.to_h.to_yaml)
      end
    
      def reload
        state = YAML.load_file(SAVED_STATE_FILE)
        @name, @address = state.values
      end
    end
    

    We can create a new user with some properties:

    user = User.new('Popeye', '123 E. Main St.')
    # => #<User:0x007fe361097058 @name="Popeye", @address="123 E. Main St.">
    

    To write that information to a file you should probably start by using YAML, which results in a very readable output and is readable by many different languages, making the data file reusable. A hash results in a very readable output:

    user.to_h
    # => {"name"=>"Popeye", "address"=>"123 E. Main St."}
    user.to_h.to_yaml
    # => "---\nname: Popeye\naddress: 123 E. Main St.\n"
    

    Save the YAML serialized hash:

    user.save
    

    Create a new version of the user without any state:

    user = User.new
    # => #<User:0x007fe361094a88 @name=nil, @address=nil>
    

    Load the saved information from the file back into the blank object:

    user.reload
    

    Which results in:

    user
    # => #<User:0x007fe361094a88 @name="Popeye", @address="123 E. Main St.">
    

    That will give you enough to work from.

    Your current code isn't going to work well though; I'd recommend reading some tutorials about Ruby classes and modules, as a Module isn't what you want, at least for your initial code.