Раздел «Язык Ruby».PhoneBook:

Телефонная книжка

Формулировка

Задача: Реализовать функциональность телефонной книжки, а именно написать класс PhoneBook и реализовать в методы

Во-вторую очередь следует реализовать методы

(загляните в документацию модуля "Marshal", и в главу про Reflection and serialization)

Затем реализуйте поиск по ключевому слову

Также продумайте вопрос, связанный с приведением телефонов и имен к каноническому виду: имена подвергните операции capitalize, а номера к виду "+7 903 123-45-67" (чтобы в случае ввода "8(903)1234567" телефон превращался в "+7 903 123-45-67").

Решения студентов:

Простейшая реализация

class PhoneBook 
  # Is initialize without params.
  #---
  # TODO: add constructor with Hash
  #+++
  def initialize
    @data = Hash.new
  end
  
  # insert record
  def insert(name, phone)
    @data[name] = phone
  end
  alias  []= insert
  
  # find record 
  def find(name)
    @data[name]
  end
  alias  [] find
  
  # find names with given phone number
  def find_by_phone(phone, &block)
    if block
      @data.each do |name,p|
        block[name,p] if p == phone
      end
    else
      @data.select do |name,p|
        p == phone
      end
    end
  end
  
  # iterate through phone book records
  def each(&block)
    @data.each(&block)
  end
  
  def size
    @data.size
  end
  
  # delete record from book
  def delete(name)
    @data.delete(name)
  end
  
  # save phone book to file
  def save(file_name)
    File.open(file_name, "w+") do |file|
      file.write(YAML.dump(@data))
    end
  end
  
  # load phone book from file
  def PhoneBook.load(file_name)
    YAML.load_file(file_name)
  end
end

  # file: using_book.rb
  require 'book'
  book = PhoneBook.new
  book["Ivan Petrov"] = "89031245678"
  book["Ivan Vasiliev"] = "89269999999"
  book["Sergey Sidorov"] = "89267777777"
  book["Olya Petrova"] = "89031245678"

  puts "\nAll:"
  book.each do |name, phone|
    printf("%20s %11s\n", name, phone)
  end

  puts "\nPeople with number 89031245678:"
  book.find_by_phone("89031245678") do  |name, phone|
    printf("%20s %11s\n", name, phone)
  end

  book.delete("Ivan Petrov")

  puts "\nAll after deletion:"
  book.each do |name, phone|
    printf("%20s %11s\n", name, phone)
  end
Результат:

> ruby using_book.rb

All:
Sergey Sidorov 89267777777
Ivan Petrov 89031245678
Olya Petrova 89031245678
Ivan Vasiliev 89269999999

People with number 89031245678:
Ivan Petrov 89031245678
Olya Petrova 89031245678

All after deletion:
Sergey Sidorov 89267777777
Olya Petrova 89031245678
Ivan Vasiliev 89269999999

Использование test/unit

require 'book'
require 'test/unit'

class TestPhoneBook < Test::Unit::TestCase
  def test_simple
    book = PhoneBook.new
    book["Ivan Petrov"] = "89031245678"
    book["Ivan Vasiliev"] = "89269999999"
    book["Sergey Sidorov"] = "89267777777"
    book["Olya Petrova"] = "89031245678"

    book.find_by_phone("89031245678") do  |name, phone|
      assert_equal("89031245678", phone)
    end

    book.delete("Ivan Petrov")
    
    assert_nil(book["Ivan Petrov"])
  end
  
  def test_save_load
    book = PhoneBook.new
    number = 89031234567
    ("aaa".."zzz").each do |name|
        book["very long prefix " + name] = number.to_s
        number += 1
    end
    book.save('c:/test.txt')  
      
    book2 = PhoneBook.load('c:/test.txt');
    
    book.each do |name,phone|
      assert_equal(book2[name], phone)
    end
    
    book2.each do |name,phone|
      assert_equal(book[name], phone)
    end
  end
end

Результат:

> ruby test_book.rb
Loaded suite test_book
Started
..
Finished in 5.391 seconds.

2 tests, 35155 assertions, 
0 failures, 0 errors