Reputation: 808
I made a program which stores strings of names in an array, it starts by asking for user input using gets.chomp, after typing ADD Name, it adds the name into an array using push, and DEL Name, to delete that name from the array, now i want to enter "REPLACE Name1 Name2" to replace Name1 with Name2 in the array. Thank you in advance :)
class Base
@@names_array = Array.new(0)
def set_names_array(name)
@@names_array.push(name)
end
def get_names_array
return @@names_array
end
def delete_name(name)
@@names_array.delete(name)
end
end
class Op
loop_flag = true
puts "Type ADD 'name' to add a name, DEL 'name' to delete, and EXIT to end program."
while loop_flag
command = gets.chomp
@nameobj = Base.new
if command[0..2] == "ADD"
@@name = command[4, command.length]
@nameobj.set_names_array(@@name)
puts "#{@@name} was added."
puts "Names:"
puts "#{@nameobj.get_names_array}"
end
if command == "EXIT"
puts "Ended."
loop_flag = false
end
if command[0..2] == "DEL"
for i in @nameobj.get_names_array
if i == command[4, command.length]
@nameobj.delete_name(i)
puts "Names:"
puts "#{@nameobj.get_names_array}"
end
end
end
if command[0..2] == "REP"
# cannot do [4, command.length] because there will be 2 names with
# various lengths which aren't fixed.
end
end
end
Upvotes: 0
Views: 115
Reputation: 211540
There's a lot of things to note here, but the most important is that while you're allowed to put free-form code within class or module definitions in practice that's discouraged except for situations where you've got no other choice, like you're doing some metaprogramming at the class or module level.
In virtually every other case you'll want to express that code either in the main context, that is outside of these definitions, or within well-defined methods you can call as required.
Digging deeper, the Base class you've defined seems to use class-level
variables exclusively. This means that all of the objects that new
produces
are functionally identical even if technically different. What you probably
want is a simple singleton version:
module NameRegistry
def self.names
@names ||= [ ]
end
end
Using this is now pretty simple, which I'll demonstrate in a second. The next thing to fix is the parser class by dramatically reducing its responsibility. You can use regular expressions to define a simple grammar that's flexible, and can easily be adapted for more unusual use cases:
class CommandParser
def parse(line)
case (line)
when /\AADD\s+(.*)\z/i
NameRegistry.names.push($1)
when /\ADEL\s+(.*)\z/i
NameRegistry.names.delete($1)
when /\AREP\s+(.*)\s+WITH\s+(.*)\z/i
if (NameRegistry.names.delete($1))
NameRegistry.names.push($2)
end
when /\AEXIT\z/i
# Signal that this command was terminal
return false
end
# Default to success
true
end
end
This leads to a chunk of main code that looks like this:
puts "Type ADD 'name' to add a name, DEL 'name' to delete, and EXIT to end program."
parser = CommandParser.new
while (parser.parse(gets.chomp))
puts "Names: #{NameRegistry.names.join(', ')}"
end
Upvotes: 1
Reputation: 91
You can add this method to Base class
:
def replace_names_array(name_to_replace, new_name)
@@names_array = @@names_array.map do |name|
name == name_to_replace ? new_name : name
end
end
Upvotes: 2