I'm trying to extend a class roster to add a delete_player method. Below is the program I'm running to work with the roster class, the error messages, and the roster.rb itself with my added code highlighted. I #!/usr/bin/ruby$: << 'lib'require 'roster'roster_klass = RosterClass.new('cfg/roster_cfg.txt')myroster = roster_klass.new("xx9.txt")if myroster.player_exists?("G_Lyne") print "Yep. He's still here\n"else print "I cut that slacker last week!!\n"endif myroster.player_exists?("D_Thacker") print "Yep. He's still here\n"else print "I cut that slacker last week!!\n"endmyroster["G_Lyne"].min = 15myroster.player_remove("X_Mosis")myroster.write_roster("xx9_modified.txt")Results:dthacker@buckbeak:~/dev/esms4/esmsdev$ ./rosterboy.rbYep. He's still hereI cut that slacker last week!!./lib/roster.rb:112:in `delete': wrong number of arguments (0 for 1) (ArgumentError) from ./lib/roster.rb:112:in `player_remove' from ./rosterboy.rb:22Library rosters.rb~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# ESMS - Electronic Soccer Management Simulator## Copyright (C) <2006> Eli Bendersky# License: LGPL (http://www.gnu.org/licenses/lgpl.html)#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~require 'yaml'require 'eliben_utils'# A factory for Rosters. Generates a Roster class from a roster# configuration file.## The configuration file defines which columns the roster contains,# in what order, and the manner in which these columns are stored# in roster files. A Roster class represents this information, by# means of an auxiliary class derived from a Struct - RosterPlayer.# This RosterPlayer class represents all the information stored# for a player. Each column defined in the configuration file is# represented by a field in the structure.## Once a some Roster class, named klass, is created, klass::RosterPlayer# can be used to access the underlying player type.## Each instance of a Roster class represents some roster file# that complies to the roster format defined by the class. The roster# is an Hash of RosterPlayer objects, keyed by names (Name is a# required column in rosters)## Usage:## # Create a new Roster class from a configuration file# roster_klass = RosterClass.new('roster_cfg.xml')## # instantiate a new Roster object from a roster file# roster = roster_klass.new("atl.txt")## # access, change or add players# minutes = roster["J_Doe"].min# roster["J_Doe"].min = 15# roster["New_Player"] = roster_klass::RosterPlayer.new# roster["New_Player"].min = 67# ...# if roster.player_exists?("D_Od") ...# ...### # write a roster into a roster file# roster.write_roster("atl_modified.txt")#module RosterClass def self.new(config_filename) roster_klass = Class.new roster_klass.class_eval do @@columns = RosterClass.parse_roster_config(config_filename) include Enumerable # Build the RosterPlayer class # @@column_ids = @@columns.map {|column| column[:id]} self.const_set('RosterPlayer', Struct.new(*@@column_ids)) # Get the column ids # def self.column_ids @@column_ids end # Create a new Roster. When no file name is given, the Roster # will be empty - you can fill it in later with calls to read_roster # or add_player # def initialize(roster_filename = nil) # @players is a Hash mapping from player name to a full RosterPlayer # object. # @players_order is an Array of player names, to retain the order in # which the players were stored in the roster # @players = Hash.new @players_order = Array.new if roster_filename read_roster(roster_filename) end end # Get a player (RosterPlayer) by name # def [](name) @players[name] end # Does this player exist in the roster ? # def player_exists?(name) !@players[name].nil? end # Change or add a player. If an unexisting player name is specified, # it is added to the roster # def []=(name, player) unless @players.include?(name) @players_order << name end @players[name] = player end###############################################My attempt at new method for removing player ################## def player_remove(name) @players.delete[name] end############################################## End of new code ################################################ # Generic /each/ iterator - iterates over players in the # roster, in the order of their appearance in the roster file. # Each yielded object is a RosterPlayer struct. # def each @players_order.each do |name| yield @players[name] end end # Reads in a roster file (verifying that it is in the correct format) # def read_roster(roster_filename) File.open(roster_filename) do |roster_file| @players = Hash.new @players_order = Array.new roster_lines = roster_file.readlines # Compare the first line with the columns definition # of the class, making sure it's a correctly formatted roster # first_line = roster_lines.shift if first_line.split.size != @@columns.size fail "Incorrect number of columns in header: expecting #{@@columns.size}" end first_line.split.each_with_index do |column, i| if @@columns[i][:name].casecmp(column) != 0 fail "Column name doesn't match configuration: '#{column}' while expecting '#{@@columns[i][:name]}'" end end # Ignore the second line - it is supposed to be a string of hyphens (---) # but we don't really care what's in it # roster_lines.shift # The rest of the roster lines are parsed and read into @players. Empty # lines are ignored. # roster_lines.each do |line| line_columns = line.split if line_columns.empty? next elsif line_columns.size != @@columns.size fail "Incorrect number of columns: expecting #{@@columns.size} in line:\n#{line}" end roster_player = self.class::RosterPlayer.new # Read each column from the line into roster_player, checking # the types of columns (and converting, where necessary) on # the way. # @@columns.each do |column| column_value = line_columns.shift if column[:type] == "Integer" if column_value.integer? column_value = Integer(column_value) else fail "Expected an Integer in column #{column[:name]}, got '#{column_value}' in line:\n#{line}" end elsif column[:type] == "Float" if column_value.float? column_value = Float(column_value) else fail "Expected a Float in column #{column[:name]}, got '#{column_value}' in line:\n#{line}" end end roster_player[column[:id]] = column_value end @players[roster_player.name] = roster_player @players_order << roster_player.name end end end # Writes a roster into a file # def write_roster(roster_filename) File.open(roster_filename, "w") do |roster_file| # Use make_roster_line to create the header line, providing column # names as the data # roster_file.puts(make_roster_line(@@columns.map {|c| c[:name]}, false)) # Create the header separation line of dashes # num_of_dashes = @@columns.inject(0) {|sum, c| sum += (c[:width] + 1)} - 1 roster_file.puts('-' * num_of_dashes) # Now dump all the players into the file # @players_order.each do |name| roster_file.puts(make_roster_line(@players[name])) end end end private # Given a RosterPlayer object, creates the line that stores this # player's details, according to the format of @@columns. # # The second optional parameter tells the method to resolve types # of columns: # true - use the format (f, d, s, etc) appropriate for the type # false - use s for all columns # def make_roster_line(player, resolve_types = true) # Build a line format from the column specification # line_format = "" @@columns.each do |column| fmt = '%' fmt += '-' if column[:align] == 'left' if resolve_types and column[:type] == 'Float' if column[:width] < 4 fail "Expecting width of at least 4 in 'Float' column #{column[:name]}" end fmt += format("%d.%d", column[:width], column[:width] - 3) else fmt += column[:width].to_s end fmt += if resolve_types case column[:type] when 'Integer' then 'd' when 'Float' then 'f' else 's' end else 's' end fmt += ' ' line_format += fmt end # remove the trailing space that the loop added # line_format.chop! # Fill in the format with the player's data # format(line_format, *player.to_a) end end roster_klass end # Reads and parses a YAML file containing the roster configuration. # On success returns the configuration in an internal format: # # An Array of columns, where each column is a Hash with the keys # :id, :name, :width, :align, :type # # :id is a 'symbol' version of :name (e.g. :nat for "Nat"), for internal # usage with the RosterPlayer type # def self.parse_roster_config(config_filename) File.open(config_filename) do |config_file| cfg = YAML::load(config_file) cfg_lines = cfg['esms_roster_format'] if cfg_lines.nil? fail "expecing 'esms_roster_format' configuration" end columns = [] cfg_lines.each_with_index do |line, line_index| unless line.keys.size == 1 fail "expecting a single entry in column number #{line_index + 1}" end name = line.keys[0] properties = line[name] column_spec = {} %w(width type).each do |required_property| if properties[required_property].nil? fail "column #{name} lacks a #{required_property} property" end column_spec[required_property.to_sym] = properties[required_property] end column_spec[:id] = name.downcase.to_sym column_spec[:name] = name column_spec[:align] = properties['align'].nil? ? 'right' : properties['align'] allowed_property_values = { :type => %w(Integer String Float), :align => %w(right left)} allowed_property_values.each do |property, values| unless values.contains?(column_spec[property]) fail "value '#{column_spec[property]}' of property '#{property.to_s}' in column #{name} is illegal" end end columns << column_spec end columns end end#########################################################################################################Program I'm using to access library is below. ###########################################################################################################