3
\$\begingroup\$

I've created a Forum website tool for admins to add, edit, and delete users from their desktop, saving to a file, and uploading the file to the database, the program is not completed I'm posting it here for review thus far

(People I'm creating it for would prefer me not having access to database, I understand I would be using activerecord model/structure if I where saving directly to the database.)

What the program does is simple:

  • It prompts the user for which he/she would like to do via add, edit, delete users.
  • The program then runs through a case statement of available options and if the option isn't found it exits the program
  • In the add_user method the program saves the input of the user into a YAML file, and prompts the user for more users, if none follow exits the program.
  • During the delete_user method, the program does the same as adding except deletes the users from the YAML file there is a bug where the program deletes the entire YAML file, not just the edited users
  • In the edit_user the program will edit various elements of the hash inside the YAML file and save over the old element of the file. Not ready yet will post follow up later

The edit user section hasn't been setup yet, still working out the kinks in delete_user method.

So what I'm looking for is:

  • A possible explanation of why the delete_user method wipes the entire file and not just the user entered, is this because I'm deleting the entire section and not just the users input?
  • Would using a JSON file be better then using a YAML file, I'm aware that A LOT of websites don't support YAML's so would it be a good idea to convert the require 'yaml' to a require 'json' and regroup from there?
  • Any possible areas of improvement? Meaning do you notice anything right off the bat that should be changed, can my syntax be updated or more developed?

Source Code:

#!/usr/bin/env ruby

require 'yaml'
require 'open-uri'

def menu
    print "Welcome to User Menu. Would you like to [A]dd users, [D]elete users, [E]dit users, [V]iew all users, or [Q]uit the system?\n"
    input = gets.chomp!
    case input
    when /a/i
        add_user
    when /d/i
        delete_user
    when /e/i
        edit_user
    when /v/i
        view_all
    else
        puts "Exiting system.."
        exit
    end
end

def add_user
    puts "Please enter Username:"
    username = gets.chomp
    data = {username: username}
    puts "Please enter user Email:"
    email = gets.chomp
    data[:email_address] = email
    puts "Please enter users status(member, vip, gold, etc..):"
    status = gets.chomp!
    data[:member_status] = status
    File.open('users.yml', 'a') { |s| s.write(data.to_yaml) }
    add_user if restart
end

def delete_user
    puts "Enter Username:"
    username = gets.chomp
    delete_data = {username: username}
    puts "Enter Email:"
    email = gets.chomp
    delete_data[:email_address] = email
    puts "Enter Status:"
    status = gets.chomp
    delete_data[:status] = status
    hash = YAML.load_file('users.yml')
    hash.delete("#{username}")
    hash.delete("#{email}")
    hash.delete("#{status}")
    File.open('users.yml', 'w') { |f| YAML.dump(delete_data.to_yaml) }
    delete_user if restart
end

def edit_user
    edit_user if restart
end

def view_all
    content = URI('#Website URL here taken out for security of site').read
end

def restart
    puts "Would you like to edit another user?"
    input = gets.chomp
    if input =~ /yes/i
        return true
    else
        puts "Exiting program.."
        exit
    end
end
menu

Overview of YAML file:

--- 
:username: TEST
:email_address: TEST
:member_status: TEST
\$\endgroup\$
2
  • 1
    \$\begingroup\$ @Caridorc's suggestions are good, and this code is pretty good as is, for a utility script this simple. One thing I'd do if it got much bigger, though, is separate the data collection from the file updates. That is, one method to collect the data. Then, having collected that data, one method which takes the full data structure and does the correct update to the file. \$\endgroup\$
    – Jonah
    Commented Nov 5, 2015 at 18:59
  • \$\begingroup\$ @Jonah I like that idea, I'll look into thanks for the feedback! \$\endgroup\$
    – 13aal
    Commented Nov 5, 2015 at 19:28

1 Answer 1

3
\$\begingroup\$

prompt function

So many times you do:

puts "Please enter Username:" # Or something else instead of Username.
username = gets.chomp

In short you print and then read input, what about a function:

def prompt(message)
  puts message
  gets.chomp
end

You can reuse it and save a lot of repetition.

Functional Programming -- No mutation

Ruby leans towards the Function Programming paradigm, so you should stick to it.

One thing is avoiding mutation:

data = {username: username}
...
data[:email_address] = email
...
data[:member_status] = status

You modify data piece by piece, instead do:

...
...
data = {username: username, email_address: email, member_status: status}

It also looks more organized to me.

In fact you may write:

data = { username: prompt("The username? "),
         email_address: prompt("The email address? ")
         member_status: prompt("The member status? ") }

And make the code shorter and more readable.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ The prompt method is an outstanding idea, thank you for that! I just edited it into my code and it looks extremely nice. Do you by chance have any idea why it is deleting the entire file? \$\endgroup\$
    – 13aal
    Commented Nov 5, 2015 at 17:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.