Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Patrick Shushereba
Patrick Shushereba
10,911 Points

Read/Write YAML File Ruby

I'm working on a bank account program as a practice project. I'm not able to get the YAML file working. The file generates, but when I open it, none of the information that is entered when the program runs is contained in the file.

require "yaml"

class BankAccount

attr_accessor :first_name, :last_name, :address, :your_account

def initialize
    @your_account = []
    open()
end

def open
    if File.exist?("accountinfo.yml")
    @your_account = YAML.load_file("accountinfo.yml")
    end
end

def save
    File.open("accountinfo.yml", "r+") do |file|
        file.write(your_account.to_yaml)
    end
end

def new_account(first_name, last_name, address)
    puts "Enter your first name:"
    self.first_name = gets.chomp
    puts "Enter your last name"
    self.last_name = gets.chomp
    puts "Enter your address:"
    self.address = gets.chomp

    self.your_account = [first_name, last_name, address]
end

def account_review(your_account)
    puts @your_acccount
end

def run
    loop do
        puts "Welcome to the bank."
        puts "1. Create New Account"
        puts "2. Review Your Account Information"
        puts "3. Check Your Balance"
        puts "4. Exit"
        puts "Enter your choice:"
            input = gets.chomp
            case input
            when '1'
                new_account(first_name, last_name, address)
            when '2'
                account_review(your_account)
            when '4'
                save()
                break
            end
    end
end

end

bank_account = BankAccount.new
bank_account.run

3 Answers

Tim Knight
Tim Knight
28,888 Points

Patrick,

Here are a few suggestions. First remember that in Ruby you don't need to put empty parentheses at the end of methods.

Based on what you're doing I didn't really see the need for creating attr_accessors, you're really just dealing with passing data around in variables from what I can tell. If you start setting data through an instance of the class that would be a different story.

Now I didn't duplicate all of your code here, just the reading and writing portion so you can see my thinking.

require "yaml"

class BankAccount

  def initialize
    @your_account = []
    load_account_details
  end

  def load_account_details
    unless File.exists?("accountinfo.yml")
      File.new("accountinfo.yml", "w+")
    end
    @your_account = YAML.load_file("accountinfo.yml")
  end

  def save_account_details
    first_name = "Tim"
    last_name = "Knight"
    address = "356 Street"
    @your_account = [first_name, last_name, address]

    File.open("accountinfo.yml", "r+") do |f|
      f.write(@your_account.to_yaml)
    end
  end

end

bank_account = BankAccount.new
bank_account.save_account_details

First notice that I'm creating the YAML file if it doesn't exist, that's going to be important if you're wanting to write the data to the file. You'll get a file doesn't exist error otherwise. Notice too that I'm just referencing the @your_account instance variable as I move the data around.

Just some thoughts.

Patrick Shushereba
Patrick Shushereba
10,911 Points

Thank you for your help. I'm working on making some changes right now. I see your point about not needing the attr_accessor. My thought was that I would need to access that data in a number of different methods. It didn't occur to me that I could just use a variable. I was just happy that the program was running. Another question that I had was I see that you have load_account_details in the initialize method. Can you explain why that is?

Tim Knight
Tim Knight
28,888 Points

It's really the same as your open() method, but I'm explaining more about what the command does by calling it load_account_details instead of just open—so reading it becomes easier. Also, remember that in Ruby you don't need empty parentheses.

Tim Knight
Tim Knight
28,888 Points

Now if you wanted to use attr_accessor you could do something like this, where you associate the name and address to the initialize method. You could then pass in those details when you create a new instance of the class or by calling setters.

Another thing to consider would be, since the your_account details is really just an array of information you've already learned, you could create that array through a method call. In this cause I created a method called details that generates the array for me based on the accessors.

class BankAccount

    attr_accessor :first_name, :last_name, :address

    def initialize(first_name="", last_name="", address="")
        @first_name = first_name
        @last_name = last_name
        @address = address
    end

    def details
       [first_name, last_name, address] 
    end
end

account = BankAccount.new
account.first_name = "Tim"
account.last_name = "Knight"
account.address = "123 Street St."

account.details     # => ["Tim", "Knight", "123 Street St."]

Again, I'm just giving you concepts... apply them if you feel they'll fit in your idea.

Patrick Shushereba
Patrick Shushereba
10,911 Points

That makes a lot of sense. I appreciate all of the help. Which one of these options would be considered the better option? Does one lead to less problems as I expand the program, or does it matter?

Tim Knight
Tim Knight
28,888 Points

I would say just start with something... you'll always likely refactor it as you learn. Just pick on that's the most comfortable right now. You'll probably have some issues with using the accessor if you just plan on blindly loading the YAML file... but if you instead load it and then set each item you'll be find. Just play with it.

Patrick Shushereba
Patrick Shushereba
10,911 Points

I made some of the changes that you suggested. I renamed the methods so they were more clear, and added the check to see if the file already existed before I load it. However, the program is still not writing to the YAML file. When I open the file up, all that is in there are hyphens on a few of the lines. What would cause something like that?

Tim Knight
Tim Knight
28,888 Points

It sounds to me that the array you're writing to the file is empty. Instead of writing the array to a file try outputting it to the screen first to help you troubleshoot.