├── 10 ├── Rakefile ├── compressor1.rb ├── compressor1_spec.rb ├── compressor2.rb ├── compressor2_spec.rb ├── compressor3.rb ├── compressor4_spec.rb ├── compressor_examples.rb ├── ex_compressor3_spec.rb ├── ex_compressor4.rb ├── ex_prose_rating1_spec.rb ├── ex_prose_rating2_spec.rb ├── ex_prose_rating3_spec.rb ├── pretentious_examples.rb └── simple_memo.rb ├── 11 ├── Rakefile ├── doc_plus.rb ├── ex_1_adddoc_spec.rb ├── ex_1_operators_are_methods_spec.rb ├── ex_2_array_shift_spec.rb ├── ex_3_doc_ops_spec.rb ├── ex_4_mix_opts_spec.rb ├── ex_5_real_world_spec.rb └── known_words.txt ├── 12 ├── Rakefile ├── document_identifier.rb ├── ex_10_good_key_spec.rb ├── ex_11_disarray_spec.rb ├── ex_12_real_world.rb ├── ex_1_equal_spec.rb ├── ex_2_impl_double_equals_spec.rb ├── ex_3_fast_double_equals_spec.rb ├── ex_4_responds_to_spec.rb ├── ex_5_kind_of_spec.rb ├── ex_6_responds_to_spec.rb ├── ex_7_trans_spec.rb ├── ex_8_regexp_spec.rb ├── ex_9_bad_key_spec.rb └── known_words.txt ├── 13 ├── Rakefile ├── ex_3_uri_spec.rb ├── ex_4_date_spec.rb ├── ex_examples1_spec.rb ├── ex_examples2_spec.rb ├── ex_examples3_spec.rb ├── ex_examples4_spec.rb ├── ex_examples5_spec.rb ├── mocha_demo.rb ├── t1.rb └── telling.txt ├── 14 ├── Rakefile ├── document_with_accessor_iv.rb ├── document_with_cv.rb ├── document_with_default_font.rb ├── document_with_iv.rb ├── document_with_iv_examples.rb ├── document_with_silly_instance_variable_spec.rb ├── ex_1_document_with_cv_spec.rb ├── ex_2_resume_presentation_spec.rb ├── ex_3_doc_disaster_spec.rb ├── ex_4_more_doc_disaster_spec.rb ├── ex_5_document_with_iv_spec.rb ├── ex_6_document_with_accessor_spec.rb ├── ex_7_resume_presentation_with_iv_spec.rb ├── ex_8_wild.rb ├── presentation.rb ├── resume.rb └── resume_presentation_with_iv.rb ├── 15 ├── Rakefile ├── demo_bit_at_a_time.rb ├── ex_print_papersize_demo.rb ├── ex_rendering.rb ├── ex_rendering_spec.rb ├── ex_wp_points_spec.rb ├── known_words.txt ├── mod_printer_classes.rb ├── mod_printer_classes_spec.rb ├── printer_classes.rb ├── trouble_mod_bad.rb ├── trouble_mod_bad_spec.rb ├── trouble_mod_good.rb ├── trouble_mod_good_spec.rb ├── word_processor.rb ├── word_processor_spec.rb └── wp_points.rb ├── 16 ├── Rakefile ├── electronic_text.rb ├── ex_1_doc_with_method_spec.rb ├── ex_2_ns_module_spec.rb ├── ex_3_prose_quality_mixin_spec.rb ├── ex_4_multiple_modules_spec.rb ├── ex_5_class_mixin_spec.rb ├── ex_6_class_extend_spec.rb ├── ex_7_override_with_local_method_spec.rb ├── ex_8_override_with_another_module_spec.rb ├── ex_9_include_constants_spec.rb ├── prose_quality_examples.rb └── writing_quality_mixin.rb ├── 17 ├── Rakefile ├── doc_each_word.rb ├── doc_with_each_char.rb ├── ex_1_basic_examples_spec.rb ├── ex_2_basic_doc_iterator_spec.rb ├── ex_3_easy_doc_iterator_spec.rb ├── ex_4_each_char_spec.rb ├── ex_5_each_word_pair_spec.rb ├── ex_6_doc_with_enum_spec.rb ├── ex_7_enumerator_spec.rb ├── ex_8_trouble.rb ├── ex_8a_except_spec.rb ├── ex_8b_each_name_ensure_spec.rb ├── ex_8c_break_spec.rb └── ex_9_real_world_spec.rb ├── 18 ├── Rakefile ├── doc_with_load_save.rb ├── ex_10_names_spec.rb ├── ex_1_simple_load_save_spec.rb ├── ex_2_simple_with_logging_spec.rb ├── ex_3_load_save_with_logging_spec.rb ├── ex_4_special_logging_methods_spec.rb ├── ex_5_swith_logging_spec.rb ├── ex_6_degenerative_xaround_spec.rb ├── ex_7_init_block_spec.rb ├── ex_8_bogus_object_spec.rb ├── ex_8a_with_database_spec.rb ├── ex_9_return_value_spec.rb └── some_application_examples.rb ├── 19 ├── Rakefile ├── doc_block_listeners.rb ├── ex_1_explicit_blocks_spec.rb ├── ex_2_doc_with_on_save_spec.rb ├── ex_3_listener_classes_spec.rb ├── ex_4_block_load_save_spec.rb ├── ex_5_archival_doc_spec.rb ├── ex_6_block_based_lazy_doc_spec.rb ├── ex_7_lambda_spec.rb ├── ex_7a_proc.rb ├── ex_8_big_array_spec.rb ├── ex_8a_array_no_block_spec.rb ├── ex_8b_big_array_fixed_spec.rb ├── ex_9_spec.rb ├── example.txt └── saveload.txt ├── 20 ├── Rakefile ├── at_exit_demo.rb ├── autoloader.rb ├── autoloader_spec.rb ├── bye.txt ├── document_reader.rb ├── ex_1_inherit_spec.rb ├── ex_1_reader_spec.rb ├── ex_2_included_spec.rb ├── ex_3_extend_include_spec.rb ├── ex_4_include_with_auto_extend_spec.rb ├── ex_4a_exit_spec.rb ├── ex_5_trace_spec.rb ├── ex_6_when_spec.rb ├── ex_7_unexpected_inherit_spec.rb ├── inherit.txt ├── inherited_demo.rb ├── plain.txt ├── plaintext_reader.rb ├── readers.rb ├── trace.txt ├── trace_func_demo.rb ├── xml_reader.rb └── yaml_reader.rb ├── 21 ├── Rakefile ├── ex_1_spec.rb ├── ex_2_repeat_spec.rb ├── ex_3_doc_missing_spec.rb ├── ex_4_doc_to_file_spec.rb ├── ex_5_soundex_spec.rb ├── ex_6_autoload_const_spec.rb ├── ex_6_const_missing_spec.rb ├── ex_7_autoload_const_spec.rb └── example.rb ├── 22 ├── Rakefile ├── ex_delegate_spec.rb ├── ex_ssdoc1_spec.rb ├── ex_ssdoc2_spec.rb ├── ex_ssdoc3_spec.rb ├── ex_ssdoc4_spec.rb ├── ex_ssdoc5_spec.rb └── ssdoc_mm.rb ├── 23 ├── Rakefile ├── ex_formletter1_spec.rb ├── ex_formletter2_spec.rb ├── ex_formletter3_spec.rb ├── ex_formletter4_spec.rb ├── ex_taskargs_spec.rb └── ostruct_spec.rb ├── 24 ├── Rakefile ├── document.rb ├── ex_1_spec.rb ├── ex_alias_method_spec.rb ├── ex_alias_patch_spec.rb ├── ex_fix_bug_spec.rb ├── ex_no_wordcount_spec.rb ├── ex_private_wordcount_spec.rb ├── ex_public_wordcount_spec.rb └── ex_string_patch_spec.rb ├── 25 ├── Rakefile ├── broken_encrypting_document.rb ├── encrypting_document.rb ├── ex_1_mostly_spec.rb ├── ex_2_one_step_spec.rb ├── ex_3_sep_classes_spec.rb ├── ex_3_twice_spec.rb ├── ex_4_encrypt_spec.rb ├── ex_5_toggle_encryption_spec.rb ├── ex_6_char_at_spec.rb ├── ex_7_char_at_switch_spec.rb ├── ex_8_reload_spec.rb ├── ex_9_better_reloadable_spec.rb ├── reloadable_document.rb ├── reloadable_document2.rb └── trouble_document.rb ├── 26 ├── Rakefile ├── disclaimer.txt ├── ex_1_struc_doc_spec.rb ├── ex_2_resume_spec.rb ├── ex_3_ins_spec.rb ├── ex_4_meta_ins_spec.rb ├── ex_4_question_spec.rb ├── ex_5_def_method_spec.rb ├── ex_6_private_doc_spec.rb ├── ex_7_private_with_class_meth_spec.rb ├── ex_8_attrs_spec.rb ├── ex_8_dumb_attrs_spec.rb ├── ex_8_simple_attr_spec.rb ├── ex_9_forwardable.rb ├── forw.rb ├── my_attr.rb ├── structured_doc_def_method.rb ├── structured_doc_eval.rb └── structured_document.rb ├── 27 ├── Rakefile ├── Rakefile.example ├── broken.ripper ├── ex_1_author.rb ├── ex_1_fix.rb ├── ex_1_simple_spec.rb ├── ex_1_title.rb ├── fellowship.xml ├── fix_author.ripper ├── fix_author_comments.ripper ├── migration_example.rb ├── on_doc_author.ripper ├── ripper1.rb ├── ripper1_fix_author.rb ├── ripper1_spec.rb ├── ripper1_title_author.rb ├── ripper2.rb ├── ripper2_demo.rb ├── ripper2_spec.rb ├── ripper3.rb ├── ripper3_demo.rb ├── ripper3_spec.rb ├── ripper4.rb ├── ripper4_main.rb ├── ripper4_spec.rb ├── ripper5.rb └── ripper5_main.rb ├── 28 ├── Rakefile ├── bad_delete.ezr ├── bad_examples.rb ├── bad_print.ezr ├── bad_print_document.ezr ├── bad_replace.ezr ├── bad_statement.ezr ├── bad_upcase.ezr ├── comments.ezr ├── common.rb ├── edit.ezr ├── ex_1_spec.rb ├── ex_2_spec.rb ├── ex_3_spec.rb ├── ex_4_spec.rb ├── ex_6_spec.rb ├── ex_erb_spec.rb ├── ex_haml_spec.rb ├── example.erb ├── example.haml ├── execute.ezr ├── ez_ripper1.rb ├── ez_ripper1_demo.rb ├── ez_ripper2.rb ├── ez_ripper2_demo.rb ├── ez_ripper3.rb ├── ez_ripper3_demo.rb ├── ez_ripper4.rb ├── ez_ripper4_demo.rb ├── ez_ripper5.rb ├── ez_ripper5_demo.rb ├── ez_ripper6.rb ├── ez_ripper_statement.rb ├── ez_ripper_statement.tt ├── ez_ripper_statement_spec.rb ├── ezr.rb ├── good_examples.rb ├── print_author.ezr ├── replace_delete.ezr ├── temp.ezr └── upcase.ezr ├── 29 ├── BachGavotteShort.mp3 ├── README.md ├── Rakefile ├── document_simple │ ├── README │ ├── Rakefile │ ├── document.gemspec │ ├── foo.rb │ ├── hoe.rb │ ├── lib │ │ └── document.rb │ ├── load_twice.rb │ ├── pkg │ │ └── document-1.0.1.gem │ └── spec │ │ └── document_spec.rb ├── ex_1_mp3info_spec.rb ├── ex_2_gem_cmds_spec.rb ├── ex_2_specific_version_spec.rb ├── file_test.rb ├── gem.install.04.cmd ├── gem.install.cmd ├── gem.install.many.cmd ├── gem.list.cmd └── versions.txt ├── .gitignore ├── 01 ├── Rakefile ├── case_spec.rb ├── com_with_example.rb ├── commented_doc.rb ├── count_words_in.rb ├── ex_1_fold_spec.rb ├── ex_case.rb ├── ex_comments_spec.rb ├── ex_constants_spec.rb ├── ex_semi_spec.rb ├── ex_trouble_spec.rb ├── less_simple_doc.rb ├── md └── parens_demo.rb ├── 02 ├── Rakefile ├── ex_bits_spec.rb ├── ex_case_spec.rb ├── ex_real_world_spec.rb ├── ex_trouble_spec.rb ├── known_words.txt ├── readonly_doc.rb ├── readonly_doc_with_unless.rb ├── until.rb ├── while_not.rb └── writable_doc.rb ├── 03 ├── 2001.txt ├── Rakefile ├── add_authors_spec.rb ├── add_authors_splat_spec.rb ├── bang.txt ├── bang_spec.rb ├── dc.xml ├── delete.txt ├── ex_each_index_word_len.rb ├── ex_each_word_len.rb ├── ex_for_word_len.rb ├── ex_inject_word_len.rb ├── ex_map_inject_word_len.rb ├── ex_trouble_bits_spec.rb ├── ex_word_freq_doc.rb ├── index_for_each_index_spec.rb ├── index_for_each_with_index_spec.rb ├── instant_spec.rb ├── known_words.txt ├── literal_spec.rb ├── load_font_spec.rb ├── map_inject_spec.rb ├── new_find_spec.rb ├── new_index_spec.rb ├── order.txt ├── order_spec.rb ├── reverse.txt ├── running_spec.rb ├── sizes.txt ├── superhero.txt ├── twinkle.txt ├── word_freq_doc_spec.rb ├── word_length_doc_spec.rb └── xmlsimple_spec.rb ├── 04 ├── Rakefile ├── bytes.txt ├── clarke.txt ├── examples_spec.rb ├── mars.txt └── sub.txt ├── 05 ├── Rakefile ├── ex_1_spec.rb ├── ex_2_spec.rb ├── examples_spec.rb ├── first_date.txt ├── mars.txt └── scanning.txt ├── 06 ├── Rakefile ├── add.rb ├── ex_demo.rb ├── ex_demo_ex1.rb ├── ex_demo_ex2.rb ├── examples_spec.rb └── known_words.txt ├── 07 ├── Rakefile ├── custom_to_s.txt ├── ex_10_spec.rb ├── ex_11_spec.rb ├── ex_12_spec.rb ├── ex_13_spec.rb ├── ex_1_spec.rb ├── ex_2_spec.rb ├── ex_3_spec.rb ├── ex_4_spec.rb ├── ex_5_spec.rb ├── ex_6_spec.rb ├── ex_7_spec.rb ├── ex_8_spec.rb ├── ex_9_spec.rb ├── ex_trouble_spec.rb ├── fake_irb.rb ├── print_word_count.txt └── variables.txt ├── 08 ├── Rakefile ├── cryptic_spec.rb ├── desc_doc.rb ├── desc_doc_spec.rb ├── ex_lazy_document.rb ├── ex_title_author_spec.rb ├── example.txt ├── gutted_doc.rb ├── gutted_doc_spec.rb ├── lazy_document_spec.rb ├── longer2_spec.rb ├── longer3_spec.rb ├── longer_spec.rb ├── title_author.rb ├── type_check_spec.rb └── wild_spec.rb ├── 09 ├── Rakefile ├── array_spec.rb ├── doc_spec.cmd ├── document.rb ├── document2_spec.rb ├── document_spec.rb ├── ex_assertion_test.rb ├── ex_bad_test_spec.rb ├── ex_clone_spec.rb ├── ex_document_test.rb ├── ex_longstring_spec.rb ├── ex_mock_spec.rb ├── ex_printable_document.rb ├── ex_printable_document_spec.rb ├── ex_run_document_spec.rb ├── ex_run_tests_spec.rb ├── ex_shoulda_test.rb ├── ex_simple_spec.rb ├── ex_starter_test.rb ├── if_spec.rb ├── known_words.txt ├── readable_document_spec.rb └── tidy_document_test.rb ├── Gemfile ├── Gemfile.lock ├── README ├── Rakefile ├── code ├── Rakefile ├── doc1.rb ├── doc2.rb ├── doc3.rb ├── doc4.rb ├── doc_access.rb ├── doc_avg_word_len.rb ├── doc_init.rb ├── doc_word_count.rb ├── doc_words.rb ├── document.rb └── simple_doc.rb ├── rvmrc.example └── utils ├── rspec_utils.rb └── tasks.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.gem 3 | *.rbc 4 | .bundle 5 | .config 6 | 20/trace.txt 7 | 07/about_me.txt 8 | 07/def_to_s.txt 9 | 09/run_spec.txt 10 | 28/example.erb.out 11 | 28/example.html 12 | -------------------------------------------------------------------------------- /01/Rakefile: -------------------------------------------------------------------------------- 1 | 2 | Targets = %w{ messy_doc.rb spec out.odt} 3 | 4 | require '../utils/tasks.rb' 5 | 6 | CLEAN.include('messy_doc.rb') 7 | 8 | 9 | file 'messy_doc.rb' do |f| 10 | code = File.read( '../code/doc3.rb' ) 11 | code = code.gsub( / /, "\t" ) 12 | new_code = '' 13 | count = 1 14 | code.each_char do |ch| 15 | unless ch == "\t" 16 | new_code << ch 17 | else 18 | if (count % 2) == 0 19 | new_code << ' ' 20 | else 21 | new_code << ' ' 22 | end 23 | end 24 | count += 1 25 | end 26 | File.open( 'messy_doc.rb', 'w') {|f| f.print(new_code)} 27 | end 28 | -------------------------------------------------------------------------------- /01/case_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require 'ex_case' 3 | 4 | describe "The example case statements" do 5 | it "should produce the right output with semicolons" do 6 | (output_of { case_semi( 'War And Peace' ) }).should == "Tolstoy\n" 7 | (output_of { case_semi( 'Romeo And Juliet' ) }).should == "Shakespeare\n" 8 | (output_of { case_semi( 'Whatever' ) }).should == "Don't know\n" 9 | end 10 | 11 | it "should produce the right output with semicolons" do 12 | (output_of { case_no_semi( 'War And Peace' ) }).should == "Tolstoy\n" 13 | (output_of { case_no_semi( 'Romeo And Juliet' ) }).should == "Shakespeare\n" 14 | (output_of { case_no_semi( 'Whatever' ) }).should == "Don't know\n" 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /01/com_with_example.rb: -------------------------------------------------------------------------------- 1 | # Class that models a plain text document, complete with title 2 | # and author: 3 | # 4 | # doc = Document.new( 'Hamlet', 'Shakespeare', 'To be or...' ) 5 | # puts doc.title 6 | # puts doc.author 7 | # puts doc.content 8 | # 9 | # Document instances know how to parse their content into words: 10 | # 11 | # puts doc.words 12 | # puts doc.word_count 13 | # 14 | class Document 15 | # class omitted... 16 | end 17 | -------------------------------------------------------------------------------- /01/commented_doc.rb: -------------------------------------------------------------------------------- 1 | # Class which represents a document 2 | class Document 3 | 4 | attr_accessor :title, :author, :content 5 | 6 | # Initialize the document, passing in the document tile, 7 | # the document author, and the text of the document 8 | def initialize(title, author, content) 9 | @title = title 10 | @author = author 11 | @content = content 12 | end 13 | 14 | # Return the words in the document 15 | 16 | def words 17 | @content.split 18 | end 19 | 20 | # Return the number of words in the document 21 | 22 | def word_count 23 | words.size 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /01/count_words_in.rb: -------------------------------------------------------------------------------- 1 | case Document 2 | def count_words_in( the_string ) ##(main 3 | the_words = the_string.split 4 | the_words.size 5 | end ##main) 6 | end 7 | -------------------------------------------------------------------------------- /01/ex_1_fold_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'folding lines' do 4 | 5 | it 'should demo a one liner with braces' do 6 | out = output_of { 7 | 10.times { |n| puts "The number is #{n}" } ##+brace 8 | } 9 | out.should match( /The number.*0.*1.*2.*9$/m ) 10 | end 11 | 12 | it 'should demo the do end version' do 13 | out = output_of { 14 | 10.times do |n| ##(do 15 | puts "The number is #{n}" 16 | puts "Twice the number is #{n*2}" 17 | end ##do) 18 | } 19 | out.should match( /The number.*0.*1.*2.*9$/m ) 20 | end 21 | end 22 | 23 | 24 | -------------------------------------------------------------------------------- /01/ex_case.rb: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | def case_no_semi(title) 4 | ##start no_semi 5 | case title 6 | when 'War And Peace' 7 | puts 'Tolstoy' 8 | when 'Romeo And Juliet' 9 | puts 'Shakespeare' 10 | else 11 | puts "Don't know" 12 | end 13 | ##end no_semi 14 | end 15 | 16 | def case_semi(title) 17 | ##start semi 18 | case title; 19 | when 'War And Peace'; puts 'Tolstoy' 20 | when 'Romeo And Juliet'; puts 'Shakespeare' 21 | else; puts "Don't know" 22 | end 23 | ##end semi 24 | end 25 | -------------------------------------------------------------------------------- /01/ex_constants_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | describe 'constant examples' do 3 | it 'should work' do 4 | FurlongsPerFortnight = 0.0001663 ##+camel 5 | ANTLERS_PER_MALE_MOOSE = 2 ##+worm 6 | 7 | defined?(FurlongsPerFortnight).should == 'constant' 8 | defined?(ANTLERS_PER_MALE_MOOSE).should == 'constant' 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /01/ex_semi_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc3' 3 | 4 | 5 | describe 'using semicolons' do 6 | 7 | it 'should let you stack statements' do 8 | doc = Document.new( 'title', 'russ', '') 9 | 10 | out = output_of { 11 | puts doc.title; puts doc.author ##+two_puts 12 | } 13 | out.should match( /title.*russ/m ) 14 | end 15 | 16 | it 'should let you define a one line class' do 17 | class DocumentException < Exception; end ##+doc_exception 18 | DocumentException.instance_of?(Class).should == true 19 | end 20 | 21 | it 'should let you define a method in one line' do 22 | def method_to_be_overriden; end ##+one_line_method 23 | method_to_be_overriden 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /01/less_simple_doc.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end 13 | 14 | def word_count 15 | words.size 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /01/md: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /01/parens_demo.rb: -------------------------------------------------------------------------------- 1 | # Some supporting stuff 2 | 3 | @content = 'It was a dark and stormy night' 4 | 5 | 6 | def find_document( title, author ) ##(find_parens 7 | # Body omitted... 8 | end 9 | 10 | # ... 11 | 12 | find_document( 'Frankenstein', 'Shelley' ) ##find_parens) 13 | 14 | 15 | 16 | def find_document title, author ##(find_no_parens 17 | # Body omitted... 18 | end 19 | 20 | # ... 21 | 22 | find_document 'Frankenstein', 'Shelley' ##find_no_parens) 23 | 24 | 25 | puts 'Look Ma, no parentheses!' ##+puts_no_parens 26 | 27 | def words ##(words_no_parens 28 | @content.split 29 | end ##words_no_parens) 30 | 31 | def words() ##(words_parens 32 | @content.split() 33 | end ##words_parens) 34 | 35 | 36 | if ( words.size < 100 ) ##(if_parens 37 | puts 'The document is not very long.' 38 | end ##if_parens) 39 | 40 | if words.size < 100 ##(if_no_parens 41 | puts 'The document is not very long.' 42 | end ##if_no_parens) 43 | -------------------------------------------------------------------------------- /02/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /02/known_words.txt: -------------------------------------------------------------------------------- 1 | NilClass 2 | -------------------------------------------------------------------------------- /02/readonly_doc.rb: -------------------------------------------------------------------------------- 1 | require '../common/document' 2 | 3 | class Document 4 | attr_accessor :read_only 5 | attr_reader :title, :author, :content 6 | 7 | # Much of the class omitted... 8 | 9 | def title=( new_title ) ##(main 10 | if not @read_only 11 | @title = new_title 12 | end 13 | end ##main) 14 | 15 | # Similar author= and content= methods omitted... 16 | 17 | end 18 | -------------------------------------------------------------------------------- /02/readonly_doc_with_unless.rb: -------------------------------------------------------------------------------- 1 | require '../common/document' 2 | 3 | class Document 4 | attr_accessor :read_only 5 | attr_reader :title, :author, :content 6 | 7 | # Much of the class omitted... 8 | 9 | def title=( new_title ) ##(main 10 | unless @read_only 11 | @title = new_title 12 | end 13 | end ##main) 14 | 15 | # Similar author= and content= methods omitted... 16 | 17 | end 18 | -------------------------------------------------------------------------------- /02/until.rb: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | def until_loop( document ) 4 | ##start 5 | until document.is_printed? 6 | document.print_next_page 7 | end 8 | ##end 9 | end 10 | 11 | 12 | end 13 | -------------------------------------------------------------------------------- /02/while_not.rb: -------------------------------------------------------------------------------- 1 | 2 | def while_not( document ) 3 | while ! document.is_printed? ##(main 4 | document.print_next_page 5 | end ##main) 6 | end 7 | -------------------------------------------------------------------------------- /02/writable_doc.rb: -------------------------------------------------------------------------------- 1 | require '../common/document' 2 | 3 | 4 | class Document ##(main 5 | attr_accessor :writable 6 | attr_reader :title, :author, :content 7 | 8 | # Much of the class omitted... 9 | 10 | def title=( new_title ) 11 | if @writable 12 | @title = new_title 13 | end 14 | end 15 | 16 | # Similar author= and content= methods omitted... 17 | 18 | end ##main) 19 | -------------------------------------------------------------------------------- /03/2001.txt: -------------------------------------------------------------------------------- 1 | [:title, "2001"] 2 | [:genre, "sci fi"] 3 | [:rating, 10] 4 | -------------------------------------------------------------------------------- /03/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /03/add_authors_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | # Most of the class omitted... 6 | 7 | def add_authors( names ) 8 | @author += " #{names.join(' ')}" 9 | end 10 | end ##main) 11 | 12 | 13 | describe Document do 14 | 15 | it 'should work like the example says' do 16 | doc = Document.new( '', 'russ', '' ) 17 | doc.add_authors( [ 'Strunk', 'White' ] ) ##+add 18 | doc.author.should == 'russ Strunk White' 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /03/add_authors_splat_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | # Most of the class omitted... 6 | 7 | def add_authors( *names ) 8 | @author += " #{names.join(' ')}" 9 | end 10 | end ##main) 11 | 12 | 13 | describe Document do 14 | 15 | it 'should work like the example says' do 16 | doc = Document.new( '', 'russ', '' ) 17 | doc.add_authors( 'Strunk', 'White' ) ##+add 18 | doc.author.should == 'russ Strunk White' 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /03/bang.txt: -------------------------------------------------------------------------------- 1 | [3, 2, 1] 2 | -------------------------------------------------------------------------------- /03/bang_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'the bang examples in the book' do 4 | 5 | it 'should have a good example of reverse and reverse!' do 6 | a = [ 1, 2, 3] ##(no_change 7 | a.reverse ##no_change) 8 | 9 | a.should == [ 1, 2, 3 ] 10 | 11 | out = output_of { 12 | pp a.reverse ##(print_both 13 | pp a ##print_both) 14 | } 15 | 16 | out.should match( /3.*2.*1.*1.*2.*3/m ) 17 | 18 | File.write( 'reverse.txt', out ) 19 | 20 | out = output_of { 21 | a.reverse! ##(print_bang 22 | pp a ##print_bang) 23 | } 24 | 25 | out.should match( /3.*2.*1/m ) 26 | 27 | File.write( 'bang.txt', out ) 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /03/dc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Spiderman 4 | Radioactive Spider 5 | 6 | 7 | Hulk 8 | Gamma Rays 9 | 10 | 11 | Reed Richards 12 | Cosmic Rays 13 | 14 | 15 | -------------------------------------------------------------------------------- /03/delete.txt: -------------------------------------------------------------------------------- 1 | [0, -9, 5, 9] 2 | -------------------------------------------------------------------------------- /03/ex_each_index_word_len.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | # A bit more idomatic, but not much ##(main 5 | 6 | def average_word_length 7 | total = 0.0 8 | words.each_index { |i| total += words[i].size } 9 | total / words.size 10 | end ##main) 11 | end 12 | -------------------------------------------------------------------------------- /03/ex_each_word_len.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | # Most of the class omitted... 6 | 7 | def average_word_length 8 | total = 0.0 9 | words.each { |word| total += word.size } 10 | 11 | total / word_count 12 | end 13 | end ##main) 14 | -------------------------------------------------------------------------------- /03/ex_for_word_len.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | # Not idiomatic at all! ##(main 5 | 6 | def average_word_length 7 | total = 0.0 8 | 9 | for i in 0...words.size 10 | total += words[i].size 11 | end 12 | 13 | total / words.size 14 | end ##main) 15 | end 16 | -------------------------------------------------------------------------------- /03/ex_inject_word_len.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def average_word_length ##(main 5 | total = words.inject(0.0){ |result, word| word.size + result} 6 | total / word_count 7 | end ##main) 8 | end 9 | -------------------------------------------------------------------------------- /03/ex_map_inject_word_len.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def average_word_length ##(main 5 | lengths = words.map { |word| word.size } 6 | len = lengths.inject { |total, word_size| word_size + total } 7 | len / words.size 8 | end ##main) 9 | end 10 | -------------------------------------------------------------------------------- /03/ex_word_freq_doc.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def word_frequencies ##(main 5 | freq = {} 6 | words.each do |word| 7 | if freq[word] 8 | freq[word] += 1 9 | else 10 | freq[word] = 1 11 | end 12 | end 13 | freq 14 | end ##main) 15 | end 16 | -------------------------------------------------------------------------------- /03/index_for_each_index_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def index_for( word ) ##(main 5 | words.each_index do |i| 6 | return i if word == words[i] 7 | end 8 | nil 9 | end ##main) 10 | end 11 | 12 | describe "index_for method" do 13 | before :each do 14 | @doc = Document.new( 'title', 'author', 'the rain in spain') 15 | end 16 | 17 | it "should return the right word indexes" do 18 | @doc.index_for( 'the' ).should == 0 19 | @doc.index_for( 'rain' ).should == 1 20 | @doc.index_for( 'spain' ).should == 3 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /03/index_for_each_with_index_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def index_for( word ) ##(main 5 | words.each_with_index do |this_word, i| 6 | return i if this_word == word 7 | end 8 | nil 9 | end ##main) 10 | end 11 | 12 | describe "index_for method" do 13 | before :each do 14 | @doc = Document.new( 'title', 'author', 'the rain in spain') 15 | end 16 | 17 | it "should return the right word indexes" do 18 | @doc.index_for( 'the' ).should == 0 19 | @doc.index_for( 'rain' ).should == 1 20 | @doc.index_for( 'spain' ).should == 3 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /03/known_words.txt: -------------------------------------------------------------------------------- 1 | find_all 2 | sort 3 | sort! 4 | ! 5 | push 6 | pop 7 | delete 8 | shift 9 | 'mom' 10 | SpecializedCollectionOfStuff 11 | -------------------------------------------------------------------------------- /03/literal_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'the literal examples in the book' do 4 | 5 | it 'should have a good example of regular and percent w array lits' do 6 | 7 | poem_words = [ 'twinkle', 'little', 'star', 'how', 'I', 'wonder' ] ##+traditional 8 | 9 | old = poem_words 10 | 11 | poem_words = %w{ twinkle little star how I wonder } ##+percent_w 12 | 13 | old.should == poem_words 14 | end 15 | 16 | it 'should have a good example of old and new style hash lits' do 17 | 18 | freq = { "I" => 1, "don't" => 1, "like" => 1, "spam" => 963 } ##+string_keys 19 | 20 | book_info = { :first_name => 'Russ', :last_name => 'Olsen' } ##+sym_keys 21 | 22 | old = book_info 23 | 24 | book_info = { first_name: 'Russ', last_name: 'Olsen' } ##+quick_hash_keys 25 | 26 | old.should == book_info 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /03/load_font_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | def load_font( specification_hash ) ##(main 4 | # Load a font according to specification_hash[:name] etc. 5 | specification_hash ##--main 6 | end ##main) 7 | 8 | describe 'default hash behavior' do 9 | 10 | it 'should work like the example says' do 11 | result = ( 12 | load_font( { :name => 'times roman', :size => 12 }) ##+paren_brace 13 | ) 14 | result.should == { name: 'times roman', size: 12 } 15 | 16 | result = ( 17 | load_font( :name => 'times roman', :size => 12 ) ##+paren 18 | ) 19 | result.should == { name: 'times roman', size: 12 } 20 | 21 | result = ( 22 | load_font :name => 'times roman', :size => 12 ##+nothing 23 | ) 24 | result.should == { name: 'times roman', size: 12 } 25 | 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /03/map_inject_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | 4 | describe "Various avg word size impls" do 5 | 6 | it "should return the right avg size with loop impl" do 7 | doc = Document.new( 'title', 'author', 'The Roots Of All Evil') 8 | lower_case_words = doc.words.map { |word| word.downcase } ##+downcase 9 | lower_case_words.should == %w{ the roots of all evil} 10 | 11 | out = output_of { 12 | pp doc.words.map { |word| word.size } ##+sizes 13 | lengths = doc.words.map { |word| word.size } 14 | lengths.should == [ 3, 5, 2, 3, 4 ] 15 | } 16 | File.write( 'sizes.txt', out ) 17 | end 18 | 19 | end 20 | -------------------------------------------------------------------------------- /03/new_find_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def index_for( word ) ##(main 5 | words.find_index { |this_word| word == this_word } 6 | end ##main) 7 | end 8 | 9 | describe "index_for method" do 10 | before :each do 11 | @doc = Document.new( 'title', 'author', 'the rain in spain') 12 | end 13 | 14 | it "should return the right word indexes" do 15 | @doc.index_for( 'the' ).should == 0 16 | @doc.index_for( 'rain' ).should == 1 17 | @doc.index_for( 'spain' ).should == 3 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /03/new_index_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document 4 | def index_for( word ) ##(main 5 | i = 0 6 | words.each do |this_word| 7 | return i if word == this_word 8 | i += 1 9 | end 10 | nil 11 | end ##main) 12 | end 13 | 14 | describe "index_for method" do 15 | before :each do 16 | @doc = Document.new( 'title', 'author', 'the rain in spain') 17 | end 18 | 19 | it "should return the right word indexes" do 20 | @doc.index_for( 'the' ).should == 0 21 | @doc.index_for( 'rain' ).should == 1 22 | @doc.index_for( 'spain' ).should == 3 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /03/order.txt: -------------------------------------------------------------------------------- 1 | [:first, "mama"] 2 | [:second, "papa"] 3 | [:third, "baby"] 4 | -------------------------------------------------------------------------------- /03/order_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'the ordered hash examples in the book' do 4 | 5 | it 'should have a good example of how hashes are ordered' do 6 | hey_its_ordered = { first: 'mama', second: 'papa', third: 'baby' } ##+hey_order 7 | 8 | out = output_of { 9 | hey_its_ordered.each { |entry| pp entry } ##+then_iterate 10 | } 11 | 12 | out.should match( /first.*second.*third/m ) 13 | File.write( 'order.txt', out ) 14 | 15 | hey_its_ordered[:fourth] = 'grandma' ##+add_grandma 16 | 17 | out = output_of { pp hey_its_ordered } 18 | out.should match( /first.*second.*third.*fourth/m ) 19 | 20 | hey_its_ordered[:first] = 'mom' 21 | 22 | out = output_of { pp hey_its_ordered } 23 | out.should match( /first.*second.*third.*fourth/m ) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /03/reverse.txt: -------------------------------------------------------------------------------- 1 | [3, 2, 1] 2 | [1, 2, 3] 3 | -------------------------------------------------------------------------------- /03/sizes.txt: -------------------------------------------------------------------------------- 1 | [3, 5, 2, 3, 4] 2 | -------------------------------------------------------------------------------- /03/superhero.txt: -------------------------------------------------------------------------------- 1 | {"super-hero"=> 2 | [{"name"=>["Spiderman"], "origin"=>["Radioactive Spider"]}, 3 | {"name"=>["Hulk"], "origin"=>["Gamma Rays"]}, 4 | {"name"=>["Reed Richards"], "origin"=>["Cosmic Rays"]}]} 5 | -------------------------------------------------------------------------------- /03/twinkle.txt: -------------------------------------------------------------------------------- 1 | ["twinkle", 2] 2 | ["little", 1] 3 | ["star", 1] 4 | -------------------------------------------------------------------------------- /03/xmlsimple_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'xmlsimple' do 4 | 5 | it 'should work like the book says' do 6 | require 'xmlsimple' ##(main 7 | data = XmlSimple.xml_in('dc.xml') ##main) 8 | 9 | data.instance_of?(Hash).should == true 10 | 11 | out = output_of { pp data } 12 | out.should match(/"super-hero".*name.*"Spiderman"/m) 13 | File.write( "superhero.txt", out ) 14 | 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /04/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /04/bytes.txt: -------------------------------------------------------------------------------- 1 | 67 2 | 108 3 | 97 4 | 114 5 | 107 6 | 101 7 | -------------------------------------------------------------------------------- /04/clarke.txt: -------------------------------------------------------------------------------- 1 | C 2 | l 3 | a 4 | r 5 | k 6 | e 7 | -------------------------------------------------------------------------------- /04/mars.txt: -------------------------------------------------------------------------------- 1 | Mars is written by Ben Bova 2 | -------------------------------------------------------------------------------- /04/sub.txt: -------------------------------------------------------------------------------- 1 | no yes 2 | no no 3 | -------------------------------------------------------------------------------- /05/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /05/first_date.txt: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /05/mars.txt: -------------------------------------------------------------------------------- 1 | Mars is written by Ben Bova 2 | -------------------------------------------------------------------------------- /05/scanning.txt: -------------------------------------------------------------------------------- 1 | 6 2 | -------------------------------------------------------------------------------- /06/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /06/add.rb: -------------------------------------------------------------------------------- 1 | def add( a, b ) 2 | a + b 3 | end 4 | -------------------------------------------------------------------------------- /06/ex_demo.rb: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | ##start ex1 4 | this is the only line of ex1 5 | ##end 6 | 7 | ##start ex2 8 | this is the first of 3 9 | 2nd 10 | third of 3 11 | ##end 12 | -------------------------------------------------------------------------------- /06/ex_demo_ex1.rb: -------------------------------------------------------------------------------- 1 | this is the only line of ex1 2 | -------------------------------------------------------------------------------- /06/ex_demo_ex2.rb: -------------------------------------------------------------------------------- 1 | this is the first of 3 2 | 2nd 3 | third of 3 4 | -------------------------------------------------------------------------------- /06/known_words.txt: -------------------------------------------------------------------------------- 1 | HashWithIndifferentAccess 2 | documents 3 | 0x29ef 4 | 0 5 | -1 6 | 'l' 7 | -------------------------------------------------------------------------------- /07/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /07/custom_to_s.txt: -------------------------------------------------------------------------------- 1 | Document: Emma by Austin 2 | -------------------------------------------------------------------------------- /07/ex_11_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/document.rb' 2 | require '../utils/rspec_utils' 3 | 4 | class Person ##(person 5 | attr_accessor :salary # A method call 6 | attr_reader :name # Another method call 7 | attr_writer :password # And another 8 | end ##person) 9 | 10 | 11 | describe 'chapter' do 12 | it 'should have good examples of suprising methods' do 13 | require 'date' # A Call to a method ##+req_date 14 | end 15 | 16 | it 'should have a working person class' do 17 | p = Person.new 18 | p.salary = 100 19 | p.name.should == nil 20 | p.password = 'xyzzy' 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /07/ex_12_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/document.rb' 2 | require '../utils/rspec_utils' 3 | 4 | class Document ##(main 5 | # Most of the class omitted... 6 | 7 | # Send this document to off via email 8 | def send( recipient ) 9 | # Do some interesting SMTP stuff... 10 | "my send" ##--main 11 | end 12 | end ##main) 13 | 14 | describe 'chapter' do 15 | it 'should have a good override send example' do 16 | doc = Document.new( 'Ethics', 'Spinoza', 'By that which is' ) 17 | doc.send('russ@russolsen.com').should == 'my send' 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /07/ex_13_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/document.rb' 2 | require '../utils/rspec_utils' 3 | 4 | class Document ##(main 5 | # Mostly omitted... 6 | 7 | def to_s 8 | "#{title} by #{aothor}" # oops! 9 | end 10 | end ##main) 11 | 12 | describe 'chapter' do 13 | it 'should have a good example of a bad to_s' do 14 | lambda { 15 | doc = Document.new( 'Ethics', 'Spinoza', 'By that which is...' ) 16 | doc.to_s 17 | }.should raise_error 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /07/ex_1_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/document.rb' 3 | 4 | class Document ##(main 5 | 6 | # Most of the class omitted... 7 | 8 | # A method 9 | 10 | def words 11 | @content.split 12 | end 13 | 14 | # And another one 15 | 16 | def word_count 17 | words.size 18 | end 19 | end ##main) 20 | 21 | describe 'chapter' do 22 | it 'should have a good document example' do 23 | doc = Document.new( 'Ethics', 'Spinoza', 'By that which is...' ) ##+make_doc 24 | doc.words.should == %w{ By that which is... } 25 | ( 26 | doc.word_count ##+get_word_count 27 | ).should == 4 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /07/ex_2_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3.rb' 2 | require '../utils/rspec_utils' 3 | 4 | class Document ##(main 5 | # Most of the class on holiday... 6 | 7 | def about_me 8 | puts "I am #{self}" 9 | puts "My title is #{self.title}" 10 | puts "I have #{self.word_count} words" 11 | end 12 | end ##main) 13 | 14 | describe 'chapter' do 15 | it 'should have a good about_me example' do 16 | doc = Document.new( 'Ethics', 'Spinoza', 'By that which is...' ) 17 | out = output_of { doc.about_me } 18 | out.should match( /I am.*My title is Ethics.*4 words/m ) 19 | File.write( "about_me.txt", out ) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /07/ex_3_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/document.rb' 2 | require '../utils/rspec_utils' 3 | 4 | # RomanceNovel is a subclass of Document, ##(main 5 | # which is a subclass of Object 6 | 7 | class RomanceNovel < Document 8 | # Lot's of steamy stuff omitted... 9 | end ##main) 10 | 11 | describe 'chapter' do 12 | it 'should have a good about_me example' do 13 | doc = RomanceNovel.new( 'Ethics', 'Spinoza', 'By that which is...' ) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /07/ex_4_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/document.rb' 2 | require '../utils/rspec_utils' 3 | 4 | describe 'chapter' do 5 | it 'should have a good everything is an object examples' do 6 | ( 7 | -3.abs # Returns 3 ##+abs_example 8 | ).should == 3 9 | 10 | # Call some methods on some objects ##(various_examples 11 | 12 | "abc".upcase 13 | :abc.length 14 | /abc/.class ##various_examples) 15 | 16 | 17 | # Call some methods on a couple of familiar objects ##(truefalse_examples 18 | 19 | true.class # Returns Trueclass 20 | false.nil? # False is close, but not nil ##truefalse_examples) 21 | 22 | ( 23 | true.class.class # Returns Class ##+true_class_example 24 | ).should == Class 25 | 26 | nil.class # Returns NilClass ##(nil_class_example 27 | nil.nil? # Yes, finally true! ##nil_class_example) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /07/ex_5_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/document.rb' 2 | require '../utils/rspec_utils' 3 | 4 | describe 'chapter' do 5 | it 'should have a good default to_s example' do 6 | out = output_of { 7 | doc = Document.new( 'Emma', 'Austin', 'Emma Woodhouse, ...' ) ##(default_to_s 8 | puts doc ##default_to_s) 9 | } 10 | out.should match( / " 3 | cmd = gets 4 | puts( eval( cmd ) ) 5 | end 6 | -------------------------------------------------------------------------------- /07/print_word_count.txt: -------------------------------------------------------------------------------- 1 | The number of words is 4 2 | -------------------------------------------------------------------------------- /07/variables.txt: -------------------------------------------------------------------------------- 1 | [:@title, :@author, :@content] 2 | -------------------------------------------------------------------------------- /08/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /08/cryptic_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/simple_doc' 3 | 4 | class Doc ##(cryptic 5 | attr_accessor :ttl, :au, :c 6 | 7 | def initialize(ttl, au, c) 8 | @ttl = ttl; @au = au; @c = c 9 | end 10 | 11 | def wds; @c.split; end 12 | end ##cryptic) 13 | 14 | describe Doc do 15 | before :each do 16 | @doc = Doc.new( 'Title', 'Russ', 'hello world' ) 17 | end 18 | 19 | it 'should keep the title author and content' do 20 | @doc.ttl.should == 'Title' 21 | @doc.au.should == 'Russ' 22 | @doc.c.should == 'hello world' 23 | end 24 | 25 | it 'should return the words in the doc' do 26 | @doc.wds[0].should == 'hello' 27 | @doc.wds[1].should == 'world' 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /08/desc_doc.rb: -------------------------------------------------------------------------------- 1 | require '../code/simple_doc.rb' 2 | 3 | class Document ##(main 4 | # Most of the class omitted... 5 | 6 | def description 7 | "#{@title.long_name} by #{@author.last_name}" 8 | end 9 | end ##main) 10 | 11 | -------------------------------------------------------------------------------- /08/desc_doc_spec.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | require "desc_doc" 3 | require 'title_author' 4 | 5 | describe Document do 6 | before :each do 7 | @title = Title.new( 'Long', 'lg', '123') 8 | @author = Author.new( 'Bob', 'Smith' ) 9 | @doc = Document.new( @title, @author, 'hello' ) 10 | end 11 | 12 | it "should hold onto title and author" do 13 | @doc.title.long_name.should == 'Long' 14 | @doc.title.short_name.should == 'lg' 15 | @doc.title.isbn.should == '123' 16 | @doc.author.first_name.should == 'Bob' 17 | @doc.author.last_name.should == 'Smith' 18 | end 19 | 20 | it 'should have a working description' do 21 | @doc.description.should == 'Long by Smith' 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /08/ex_title_author_spec.rb: -------------------------------------------------------------------------------- 1 | require 'ex_lazy_document' 2 | require 'title_author' 3 | 4 | describe Title do 5 | it "should hold onto its attributes" do 6 | t = Title.new( 'dick and jane', 'd&j', '1234') 7 | t.long_name.should == 'dick and jane' 8 | t.short_name.should == 'd&j' 9 | t.isbn.should == '1234' 10 | end 11 | end 12 | 13 | describe Author do 14 | it "should hold onto its attributes" do 15 | a = Author.new( 'russ', 'olsen' ) 16 | a.first_name.should == 'russ' 17 | a.last_name.should == 'olsen' 18 | end 19 | 20 | it "should look like example in book" do 21 | 22 | two_cities = Title.new( 'A Tale Of Two Cities', ##(2cities 23 | '2 Cities', '0-999-99999-9' ) 24 | dickens = Author.new( 'Charles', 'Dickens' ) 25 | doc = Document.new( two_cities, dickens, 'It was the best...' ) ##2cities) 26 | 27 | two_cities.long_name.should == 'A Tale Of Two Cities' 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /08/example.txt: -------------------------------------------------------------------------------- 1 | a 2 | a 3 | a 4 | -------------------------------------------------------------------------------- /08/gutted_doc.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | # Body of the class unchanged... 3 | end 4 | 5 | class LazyDocument 6 | # Body of the class unchanged... 7 | end 8 | -------------------------------------------------------------------------------- /08/gutted_doc_spec.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | require "#{File.dirname(__FILE__)}/gutted_doc" 3 | 4 | describe Document do 5 | it "should be a class" do 6 | Document.class.should == Class 7 | doc = Document.new 8 | end 9 | end 10 | 11 | describe LazyDocument do 12 | it "should be a class" do 13 | LazyDocument.class.should === Class 14 | doc = LazyDocument.new 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /08/longer2_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/simple_doc' 3 | 4 | class Document 5 | def is_longer_than?( number_of_characters ) ##(longer 6 | @content.length > number_of_characters 7 | end ##longer) 8 | end 9 | 10 | describe "is longer than" do 11 | it 'return true if arg is bigger than size' do 12 | doc = Document.new( 'a doc', 'russ', 'abc' ) 13 | doc.is_longer_than?( 1 ).should == true 14 | doc.is_longer_than?( 2 ).should == true 15 | doc.is_longer_than?( 3 ).should == false 16 | doc.is_longer_than?( 4 ).should == false 17 | doc.is_longer_than?( 999 ).should == false 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /08/longer3_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/simple_doc' 3 | 4 | class Document 5 | # Given a number, which needs to be an instance of Numeric, ##(longer 6 | # return true if the number of characters in the document 7 | # exceeds the number. 8 | def is_longer_than?( number_of_characters ) 9 | @content.length > number_of_characters 10 | end ##longer) 11 | end 12 | 13 | describe "is longer than" do 14 | it 'return true if arg is bigger than size' do 15 | doc = Document.new( 'a doc', 'russ', 'abc' ) 16 | doc.is_longer_than?( 1 ).should == true 17 | doc.is_longer_than?( 2 ).should == true 18 | doc.is_longer_than?( 3 ).should == false 19 | doc.is_longer_than?( 4 ).should == false 20 | doc.is_longer_than?( 999 ).should == false 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /08/longer_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/simple_doc' 3 | 4 | class Document 5 | def is_longer_than?( n ) ##(longer 6 | @content.length > n 7 | end ##longer) 8 | end 9 | 10 | describe "is longer than" do 11 | it 'return true if arg is bigger than size' do 12 | doc = Document.new( 'a doc', 'russ', 'abc' ) 13 | doc.is_longer_than?( 1 ).should == true 14 | doc.is_longer_than?( 2 ).should == true 15 | doc.is_longer_than?( 3 ).should == false 16 | doc.is_longer_than?( 4 ).should == false 17 | doc.is_longer_than?( 999 ).should == false 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /08/title_author.rb: -------------------------------------------------------------------------------- 1 | class Title 2 | attr_reader :long_name, :short_name 3 | attr_reader :isbn 4 | 5 | def initialize(long_name, short_name, isbn) 6 | @long_name = long_name 7 | @short_name = short_name 8 | @isbn = isbn 9 | end 10 | end 11 | 12 | class Author 13 | attr_reader :first_name, :last_name 14 | 15 | def initialize( first_name, last_name ) 16 | @first_name = first_name 17 | @last_name = last_name 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /08/type_check_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/simple_doc' 3 | 4 | class Document 5 | def initialize( title, author, content ) ##(bad_type 6 | raise "title isn't a String" unless title.kind_of? String 7 | raise "author isn't a String" unless author.kind_of? String 8 | raise "content isn't a String" unless content.kind_of? String 9 | @title = title 10 | @author = author 11 | @content = content 12 | end ##bad_type) 13 | end 14 | 15 | describe "bad type checking" do 16 | it 'should throw and error if the title isnt a string' do 17 | lambda { doc = Document.new( 1, "", "" )}.should raise_error(RuntimeError) 18 | end 19 | 20 | it 'should throw and error if the author isnt a string' do 21 | lambda { doc = Document.new( "", 1, "" )}.should raise_error(RuntimeError) 22 | end 23 | 24 | it 'should throw and error if the content isnt a string' do 25 | lambda { doc = Document.new( "", "", 1 )}.should raise_error(RuntimeError) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /08/wild_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | describe "in the wild examples" do 4 | 5 | it "should have a good file open example" do 6 | open_file = File.open( '/etc/passwd' ) ##+open 7 | open_file.close 8 | end 9 | 10 | it 'should have a good stringio example' do 11 | require 'stringio' ##(sio 12 | open_string = StringIO.new( "So say we all!\nSo say we all!\n" ) ##sio) 13 | end 14 | 15 | it 'should have a good set example' do 16 | require 'set' 17 | five_even = [ 2, 4, 6, 8, 10 ] ##(set 18 | five_even_set = Set.new( five_even ) ##set) 19 | five_even_set.size.should == 5 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /09/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /09/array_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#each" do 2 | it "yields each element to the block" do 3 | a = [] 4 | x = [1, 2, 3] 5 | x.each { |item| a << item }.should equal(x) 6 | a.should == [1, 2, 3] 7 | end 8 | 9 | # Lots of stuff omitted 10 | end 11 | -------------------------------------------------------------------------------- /09/doc_spec.cmd: -------------------------------------------------------------------------------- 1 | rspec document_spec.rb 2 | -------------------------------------------------------------------------------- /09/document.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | -------------------------------------------------------------------------------- /09/document2_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | describe Document do 4 | it 'should hold on to the contents' do 5 | text = 'A bunch of words' 6 | doc = Document.new( 'test', 'nobody', text ) 7 | doc.content.should == text 8 | end 9 | 10 | it 'should return all of the words in the document' do 11 | text = 'A bunch of words' 12 | doc = Document.new( 'test', 'nobody', text ) 13 | doc.content.should match( /A bunch.*/ ) 14 | doc.words.include?( 'bunch' ).should == true ##+simple_should 15 | doc.words.should include( 'bunch' ) ##+should_include 16 | doc.words.should include( 'of' ) 17 | doc.words.should include( 'words' ) 18 | doc.words.should_not include( 'Excelsior' ) 19 | end 20 | 21 | it 'should know how many words it contains' do 22 | text = 'A bunch of words' 23 | doc = Document.new( 'test', 'nobody', text ) 24 | doc.word_count.should == 4 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /09/document_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | describe Document do ##(main 4 | it 'should hold on to the contents' do 5 | text = 'A bunch of words' 6 | doc = Document.new( 'test', 'nobody', text ) 7 | doc.content.should == text 8 | end 9 | 10 | it 'should return all of the words in the document' do 11 | text = 'A bunch of words' 12 | doc = Document.new( 'test', 'nobody', text ) 13 | doc.words.include?( 'A' ).should == true 14 | doc.words.include?( 'bunch' ).should == true 15 | doc.words.include?( 'of' ).should == true 16 | doc.words.include?( 'words' ).should == true 17 | end 18 | 19 | it 'should know how many words it contains' do 20 | text = 'A bunch of words' 21 | doc = Document.new( 'test', 'nobody', text ) 22 | doc.word_count.should == 4 23 | end 24 | end ##main) 25 | -------------------------------------------------------------------------------- /09/ex_assertion_test.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require '../code/doc3' 3 | 4 | 5 | class DocumentTest < Test::Unit::TestCase 6 | 7 | def test_assert_match 8 | assert_match /times.*/, 'times new roman' ##+match 9 | end 10 | 11 | def test_instance_of 12 | assert_instance_of String, 'hello' ##+instance 13 | end 14 | 15 | def test_raise 16 | assert_raise ZeroDivisionError do ##(with_raise 17 | x = 1/0 18 | end ##with_raise) 19 | end 20 | 21 | def test_no_raise 22 | assert_nothing_thrown do ##(no_raise 23 | x = 1/2 24 | end ##no_raise) 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /09/ex_bad_test_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'a bad test' do 2 | 3 | before :each do 4 | @message = 'error error error' 5 | end 6 | 7 | # This test should was meant to fail, but doesn't 8 | 9 | it 'should not have an error message' do 10 | found_error = @message =~ /error/ 11 | found_error.should_not == true 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /09/ex_document_test.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | require 'test/unit' ##(main 3 | require 'document.rb' 4 | 5 | class DocumentTest < Test::Unit::TestCase 6 | def test_document_holds_onto_contents ##(one_method 7 | text = 'A bunch of words' 8 | doc = Document.new('test', 'nobody', text) 9 | assert_equal text, doc.content, 'Contents are still there' ##+with_comment 10 | end ##one_method) 11 | 12 | def test_that_doc_can_return_words_in_array 13 | text = 'A bunch of words' 14 | doc = Document.new('test', 'nobody', text) 15 | assert doc.words.include?( 'A' ) 16 | assert doc.words.include?( 'bunch' ) ##+plain_assert 17 | assert doc.words.include?( 'of' ) 18 | assert doc.words.include?( 'words' ) 19 | end 20 | 21 | def test_that_word_count_is_correct 22 | text = 'A bunch of words' 23 | doc = Document.new('test', 'nobody', text) 24 | assert_equal 4, doc.word_count, 'Word count is correct' 25 | end 26 | end ##main) 27 | -------------------------------------------------------------------------------- /09/ex_longstring_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'stubbing an apparently long string' do 2 | 3 | it 'should know how to make a string look long' do 4 | 5 | apparently_long_string = 'actually short' ##(main 6 | apparently_long_string.stub!( :length ).and_return( 1000000 ) ##main) 7 | 8 | apparently_long_string.should == 'actually short' 9 | apparently_long_string.length.should == 1000000 10 | end 11 | 12 | end 13 | -------------------------------------------------------------------------------- /09/ex_mock_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'mocking with rspec' do 2 | before :each do 3 | @doc = mock 4 | @doc.should_receive(:check_spelling).and_return('correct') 5 | end 6 | 7 | it 'should know how to print itself' do ##(main 8 | mock_printer = mock('Printer') 9 | mock_printer.should_receive(:available?).and_return(true) 10 | mock_printer.should_receive(:render).exactly(3).times 11 | @doc.check_spelling( mock_printer ).should == 'correct' ##main) 12 | 13 | @doc = mock 14 | mock_printer.available?.should == true 15 | 3.times { mock_printer.render } 16 | end ##+main 17 | end 18 | 19 | -------------------------------------------------------------------------------- /09/ex_printable_document.rb: -------------------------------------------------------------------------------- 1 | require 'document' 2 | 3 | class PrintableDocument < Document ##(main 4 | def print( printer ) 5 | return 'Printer unavailable' unless printer.available? 6 | printer.render( "#{title}\n" ) 7 | printer.render( "By #{author}\n" ) 8 | printer.render( content ) 9 | 'Done' 10 | end 11 | end ##main) 12 | -------------------------------------------------------------------------------- /09/ex_printable_document_spec.rb: -------------------------------------------------------------------------------- 1 | require 'ex_printable_document' 2 | 3 | describe PrintableDocument do ##(main 4 | before :each do 5 | @text = 'A bunch of words' 6 | @doc = PrintableDocument.new( 'test', 'nobody', @text ) 7 | end 8 | 9 | it 'should know how to print itself' do 10 | stub_printer = stub :available? => true, :render => nil ##+stub_printer 11 | @doc.print( stub_printer ).should == 'Done' 12 | end 13 | 14 | it 'should return the proper string if printer is offline' do 15 | stub_printer = stub :available? => false, :render => nil 16 | @doc.print( stub_printer ).should == 'Printer unavailable' 17 | end 18 | end ##main) 19 | -------------------------------------------------------------------------------- /09/ex_run_document_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'running the document spec' do 4 | it 'should work like described in the book' do 5 | cmd = "`#{File.read( "doc_spec.cmd" )}`" 6 | out = eval cmd 7 | out.should match( /\.\..*Finished/m ) 8 | File.write( 'run_spec.txt', out ) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /09/ex_run_tests_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'unit tests' do 2 | it 'should pass when you run it' do 3 | Dir['*_test.rb'].sort.each do |test_file| 4 | puts test_file 5 | puts ">> #{test_file}" 6 | system("ruby -I . #{test_file}").should == true 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /09/ex_shoulda_test.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require 'shoulda' 3 | require 'document.rb' 4 | 5 | class DocumentTest < Test::Unit::TestCase 6 | context 'A basic document class' do 7 | def setup 8 | @text = 'A bunch of words' 9 | @doc = Document.new('a test', 'russ', @text) 10 | end 11 | 12 | should 'hold on to the contents' do 13 | assert_equal @text, @doc.content, 'Contents still there' 14 | end 15 | 16 | # Rest of the test omitted... 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /09/ex_simple_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | describe Document do ##(main 4 | it 'should not catch fire when you create an instance' do 5 | Document.new( 'title', 'author', 'stuff' ).should_not == nil 6 | end 7 | end ##main) 8 | -------------------------------------------------------------------------------- /09/ex_starter_test.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | require 'test/unit' 3 | require 'document.rb' 4 | 5 | class DocumentTest < Test::Unit::TestCase 6 | def test_document_holds_onto_contents ##(one_method 7 | text = 'A bunch of words' 8 | doc = Document.new('test', 'nobody', text) 9 | assert_equal text, doc.content 10 | end ##one_method) 11 | end 12 | -------------------------------------------------------------------------------- /09/if_spec.rb: -------------------------------------------------------------------------------- 1 | describe "The if expression" do 2 | it "evaluates body if expression is true" do 3 | a = [] 4 | if true 5 | a << 123 6 | end 7 | a.should == [123] 8 | end 9 | 10 | it "does not evaluate body if expression is false" do 11 | a = [] 12 | if false 13 | a << 123 14 | end 15 | a.should == [] 16 | end 17 | 18 | # Lots and lots of stuff omitted 19 | end 20 | -------------------------------------------------------------------------------- /09/known_words.txt: -------------------------------------------------------------------------------- 1 | assert 2 | assert_equal 3 | assert_nil 4 | assert_not_equal 5 | assert_not_nil 6 | test_that_it_works 7 | test_number_four 8 | teardown 9 | after 10 | -------------------------------------------------------------------------------- /09/readable_document_spec.rb: -------------------------------------------------------------------------------- 1 | require 'document' ##(main 2 | 3 | describe Document do 4 | before :each do 5 | @text = 'A bunch of words' 6 | @doc = Document.new( 'test', 'nobody', @text ) 7 | end 8 | 9 | it 'should hold on to the contents' do 10 | @doc.content.should == @text 11 | end 12 | 13 | it 'should know which words it has' do 14 | @doc.words.should include( 'A' ) 15 | @doc.words.should include( 'bunch' ) 16 | @doc.words.should include( 'of' ) 17 | @doc.words.should include( 'words' ) 18 | end 19 | 20 | it 'should know how many words it contains' do 21 | @doc.word_count.should == 4 22 | end 23 | 24 | end ##main) 25 | -------------------------------------------------------------------------------- /09/tidy_document_test.rb: -------------------------------------------------------------------------------- 1 | require 'document.rb' 2 | require 'test/unit' 3 | 4 | class DocumentTest < Test::Unit::TestCase ##(main 5 | def setup 6 | @text = 'A bunch of words' 7 | @doc = Document.new('test', 'nobody', @text) 8 | end 9 | 10 | def test_that_document_holds_onto_contents 11 | assert_equal @text, @doc.content, 'Contents are still there' 12 | end 13 | 14 | def test_that_doc_can_return_words_in_array 15 | assert @doc.words.include?( 'A' ) 16 | assert @doc.words.include?( 'bunch' ) 17 | assert @doc.words.include?( 'of' ) 18 | assert @doc.words.include?( 'words' ) 19 | end 20 | 21 | def test_that_word_count_is_correct 22 | assert_equal 4, @doc.word_count, 'Word count is correct' 23 | end 24 | end ##main) 25 | -------------------------------------------------------------------------------- /10/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /10/compressor1.rb: -------------------------------------------------------------------------------- 1 | class TextCompressor 2 | attr_reader :unique, :index 3 | 4 | def initialize( text ) 5 | @unique = [] 6 | @index = [] 7 | 8 | words = text.split 9 | words.each do |word| 10 | i = @unique.index( word ) 11 | if i 12 | @index << i 13 | else 14 | @unique << word 15 | @index << unique.size - 1 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /10/compressor1_spec.rb: -------------------------------------------------------------------------------- 1 | require 'compressor1' 2 | require 'compressor_examples' 3 | 4 | 5 | describe "Examples int he book" do 6 | it 'should match the example' do 7 | text = "This specification is the spec for a specification" ##(make 8 | compressor = TextCompressor.new( text ) ##make) 9 | 10 | unique_word_array = compressor.unique ##(use 11 | word_index = compressor.index ##use) 12 | 13 | unique_word_array.class.should == Array 14 | word_index.class.should == Array 15 | unique_word_array[word_index[0]].should == 'This' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /10/compressor2.rb: -------------------------------------------------------------------------------- 1 | 2 | class TextCompressor 3 | attr_reader :unique, :index 4 | 5 | def initialize( text ) 6 | @unique = [] 7 | @index = [] 8 | 9 | words = text.split 10 | words.each do |word| 11 | i = unique_index_of( word ) 12 | if i 13 | @index << i 14 | else 15 | @index << add_unique_word( word ) 16 | end 17 | end 18 | end 19 | 20 | def unique_index_of( word ) 21 | @unique.index(word) 22 | end 23 | 24 | def add_unique_word( word ) 25 | @unique << word 26 | unique.size - 1 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /10/compressor2_spec.rb: -------------------------------------------------------------------------------- 1 | require 'compressor2' 2 | require 'compressor_examples' 3 | -------------------------------------------------------------------------------- /10/compressor3.rb: -------------------------------------------------------------------------------- 1 | 2 | class TextCompressor 3 | attr_reader :unique, :index 4 | 5 | def initialize( text ) 6 | @unique = [] 7 | @index = [] 8 | add_text( text ) 9 | end 10 | 11 | def add_text( text ) 12 | words = text.split 13 | words.each { |word| add_word( word ) } 14 | end 15 | 16 | def add_word( word ) 17 | i = unique_index_of( word ) || add_unique_word( word ) 18 | @index << i 19 | end 20 | 21 | def unique_index_of( word ) 22 | @unique.index(word) 23 | end 24 | 25 | def add_unique_word( word ) 26 | @unique << word 27 | unique.size - 1 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /10/compressor4_spec.rb: -------------------------------------------------------------------------------- 1 | require 'ex_compressor4' 2 | require 'compressor_examples' 3 | -------------------------------------------------------------------------------- /10/ex_compressor3_spec.rb: -------------------------------------------------------------------------------- 1 | require 'compressor3' 2 | require 'compressor_examples' 3 | 4 | describe TextCompressor do ##(main 5 | 6 | it "should be able to add some text" do 7 | c = TextCompressor.new( '' ) 8 | c.add_text( 'first second' ) 9 | c.unique.should == [ 'first', 'second' ] 10 | c.index.should == [ 0, 1 ] 11 | end 12 | 13 | it "should be able to add a word" do 14 | c = TextCompressor.new( '' ) 15 | c.add_word( 'first' ) 16 | c.unique.should == [ 'first' ] 17 | c.index.should == [ 0 ] 18 | end 19 | 20 | it "should be able to find the index of a word" do 21 | c = TextCompressor.new( 'hello world' ) 22 | c.unique_index_of( 'hello' ).should == 0 23 | c.unique_index_of( 'world' ).should == 1 24 | end 25 | 26 | # ... 27 | end ##main) 28 | -------------------------------------------------------------------------------- /10/ex_compressor4.rb: -------------------------------------------------------------------------------- 1 | class TextCompressor 2 | attr_reader :unique, :index 3 | 4 | def initialize( text ) 5 | @unique = [] 6 | @index = [] 7 | add_text( text ) 8 | end 9 | 10 | def add_text( text ) 11 | words = text.split 12 | words.each { |word| add_word( word ) } 13 | end 14 | 15 | def add_word( word ) 16 | i = unique_index_of( word ) || add_unique_word( word ) 17 | @index << i 18 | end 19 | 20 | def unique_index_of( word ) 21 | @unique.index(word) 22 | end 23 | end 24 | 25 | class TextCompressor ##(main 26 | # ... 27 | 28 | def add_unique_word( word ) 29 | add_word_to_unique_array( word ) 30 | last_index_of_unique_array 31 | end 32 | 33 | def add_word_to_unique_array( word ) 34 | @unique << word 35 | end 36 | 37 | def last_index_of_unique_array 38 | unique.size - 1 39 | end 40 | end ##main) 41 | -------------------------------------------------------------------------------- /10/pretentious_examples.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | describe 'Pretentions ratings' do 4 | it 'should return the right rating' do 5 | doc = Document.new( 1.0, 0.1 ).prose_rating.should == :really_pretentious 6 | doc = Document.new( 1.0, 0.199 ).prose_rating.should == :really_pretentious 7 | doc = Document.new( 1.0, 0.3 ).prose_rating.should == :somewhat_pretentious 8 | doc = Document.new( 1.0, 0.4 ).prose_rating.should == :somewhat_pretentious 9 | 10 | doc = Document.new( 0.2, 0.1 ).prose_rating.should == :about_right 11 | doc = Document.new( 0.2, 0.199 ).prose_rating.should == :about_right 12 | doc = Document.new( 0.19, 0.9 ).prose_rating.should == :about_right 13 | 14 | doc = Document.new( 0.0, 0.4 ).prose_rating.should == :really_informal 15 | doc = Document.new( 0.05, 0.29 ).prose_rating.should == :somewhat_informal 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /10/simple_memo.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | class 4 | -------------------------------------------------------------------------------- /11/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | 3 | CLEAN.include(%w{notbest.txt total.txt type_error.txt unsure.txt}) 4 | 5 | -------------------------------------------------------------------------------- /11/doc_plus.rb: -------------------------------------------------------------------------------- 1 | class Document ##(class 2 | # Most of the class omitted... 3 | 4 | def +(other) ##(method 5 | Document.new( title, author, "#{content} #{other.content}" ) 6 | end ##method) 7 | end ##class) 8 | -------------------------------------------------------------------------------- /11/ex_1_adddoc_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | require 'pp' 4 | 5 | require 'doc_plus.rb' 6 | 7 | describe Document do 8 | it "should be able to add" do 9 | 10 | out = output_of { 11 | doc1 = Document.new('Tag Line1', 'Kirk', "These are the voyages") ##(ex 12 | doc2 = Document.new('Tag Line2', 'Kirk', "of the star ship ...") 13 | 14 | total_document = doc1 + doc2 15 | puts total_document.content ##ex) 16 | } 17 | out.should match(/These.*star ship*/) 18 | File.write( 'total.txt', out) 19 | 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /11/ex_1_operators_are_methods_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | describe 'operators are methods' do 3 | it '+ should be a method call' do 4 | first = mock 5 | second = mock 6 | first.should_receive(:+).twice.with(second).and_return(:the_sum) 7 | 8 | sum = first + second ##+op1 9 | sum.should == :the_sum 10 | 11 | sum = first.+(second) ##+method1 12 | sum.should == :the_sum 13 | end 14 | 15 | it 'should do the methods in the right order' do 16 | fourth = mock 17 | third = mock 18 | second = mock 19 | first = mock 20 | 21 | third.should_receive(:-).twice.with(fourth).and_return(:aaa) 22 | second.should_receive(:*).twice.with(:aaa).and_return(:bbb) 23 | first.should_receive(:+).twice.with(:bbb).and_return(:ccc) 24 | 25 | result = first + second * (third - fourth) ##+op2 26 | result.should == :ccc 27 | 28 | result = first.+(second.*(third.-(fourth))) ##+method2 29 | result.should == :ccc 30 | 31 | end 32 | end 33 | 34 | 35 | -------------------------------------------------------------------------------- /11/ex_2_array_shift_spec.rb: -------------------------------------------------------------------------------- 1 | describe Array do 2 | it 'should be able to shift new items in' do 3 | names = [] ##(main 4 | names << 'Rob' # names.size is now 1 5 | names << 'Denise' # names.size is now 2 ##main) 6 | 7 | names.should == %w{ Rob Denise } 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /11/known_words.txt: -------------------------------------------------------------------------------- 1 | foo 2 | and 3 | Float 4 | Vector 5 | Matrix 6 | Set 7 | Fixnum 8 | sprintf 9 | -------------------------------------------------------------------------------- /12/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /12/document_identifier.rb: -------------------------------------------------------------------------------- 1 | class DocumentIdentifier 2 | attr_reader :folder, :name 3 | 4 | def initialize( folder, name ) 5 | @folder = folder 6 | @name = name 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /12/ex_11_disarray_spec.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | 3 | class DisArray ##(main 4 | 5 | attr_reader :my_array 6 | 7 | def initialize 8 | @my_array = [] 9 | end 10 | 11 | def ==(other) 12 | return false unless other.kind_of?(DisArray) 13 | @my_array == other.my_array 14 | end 15 | 16 | def eql?(other) 17 | return false unless other.kind_of?(DisArray) 18 | @my_array.eql?( other.my_array ) 19 | end 20 | 21 | def hash 22 | @my_array.hash 23 | end 24 | 25 | # Rest of the class omitted... 26 | end ##main) 27 | 28 | 29 | describe DisArray do 30 | before :each do 31 | @da = DisArray.new 32 | end 33 | 34 | it 'should have a good == method' do 35 | @da.should == @da 36 | (@da == DisArray.new).should == true 37 | end 38 | 39 | it 'should work in a hash' do 40 | hash = {} 41 | hash[@da] = 1 42 | hash[@da].should == 1 43 | hash[DisArray.new].should == 1 44 | hash[:whatever].should == nil 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /12/ex_1_equal_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'document_identifier' 3 | 4 | describe DocumentIdentifier do 5 | 6 | it "should repect equal?" do 7 | i1 = DocumentIdentifier.new( 'books', 'warandpeace' ) 8 | i2 = i1 9 | i3 = DocumentIdentifier.new( 'books', 'warandpeace' ) 10 | i1.equal?(i1).should == true 11 | i1.equal?(i2).should == true 12 | i1.equal?(i3).should == false 13 | end 14 | 15 | it "should have the default ==" do 16 | first_id = DocumentIdentifier.new( 'secret/plans', 'raygun.txt' ) ##(intro 17 | second_id = DocumentIdentifier.new('secret/plans', 'raygun.txt' ) 18 | 19 | puts "They are equal!" if first_id == second_id ##intro) 20 | 21 | (first_id == second_id).should == false 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /12/ex_3_fast_double_equals_spec.rb: -------------------------------------------------------------------------------- 1 | require 'document_identifier' 2 | require '../utils/rspec_utils' 3 | 4 | class DocumentIdentifier ##(doc_id 5 | 6 | # ... 7 | 8 | def ==(other) 9 | return true if other.equal?(self) 10 | return false unless other.instance_of?(self.class) 11 | folder == other.folder && name == other.name 12 | end 13 | end ##doc_id) 14 | 15 | 16 | 17 | describe DocumentIdentifier do 18 | 19 | it "should have the a good ==" do 20 | first_id = DocumentIdentifier.new( 'secret/plans', 'raygun.txt' ) 21 | second_id = DocumentIdentifier.new('secret/plans', 'raygun.txt' ) 22 | 23 | (first_id == first_id).should == true 24 | (first_id == second_id).should == true 25 | (first_id == 444).should == false 26 | 27 | output_of { 28 | puts "They are equal!" if first_id == second_id ##+demo 29 | }.should == "They are equal!\n" 30 | end 31 | 32 | end 33 | -------------------------------------------------------------------------------- /12/ex_6_responds_to_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'document_identifier' 3 | 4 | class DocumentIdentifier 5 | 6 | # ... 7 | 8 | def ==(other) 9 | return false unless other.respond_to?(:folder) 10 | return false unless other.respond_to?(:name) 11 | folder == other.folder && name == other.name 12 | end 13 | end 14 | 15 | 16 | 17 | class DocumentPointer 18 | attr_reader :folder, :name 19 | 20 | def initialize( folder, name ) 21 | @folder = folder 22 | @name = name 23 | end 24 | end 25 | 26 | describe DocumentIdentifier do 27 | 28 | it 'should be equal to a doc pointer' do 29 | identifier = DocumentIdentifier.new( 'secret/map', 'area51.gif' ) 30 | pointer = DocumentPointer .new('secret/map', 'area51.gif' ) 31 | 32 | (identifier == pointer).should == true 33 | (pointer == identifier).should == false 34 | end 35 | end 36 | 37 | -------------------------------------------------------------------------------- /12/ex_8_regexp_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | describe Regexp do 4 | 5 | it 'should support =~ as matching and == as equality' do 6 | ( 7 | /Roswell.*/ =~ 'Roswell' # Yes! ##+main 8 | ).should_not == nil 9 | 10 | ( 11 | /Roswell.*/ == 'Roswell' # No! ##+main 12 | ).should == false # No! 13 | end 14 | 15 | it 'should work in a case statement' do 16 | result = '' 17 | location = 'area 51' ##(case 18 | 19 | case location 20 | when /area.*/ 21 | # ... 22 | result = 'A51' ##--case 23 | when /roswell.*/ 24 | # ... 25 | else 26 | # ... 27 | end ##case) 28 | 29 | result.should == 'A51' 30 | end 31 | 32 | end 33 | 34 | -------------------------------------------------------------------------------- /12/ex_9_bad_key_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require 'document_identifier' 3 | 4 | class DocumentIdentifier 5 | 6 | # ... 7 | 8 | def ==(other) 9 | return false unless other.respond_to?(:folder) 10 | return false unless other.respond_to?(:name) 11 | folder == other.folder && name == other.name 12 | end 13 | end 14 | 15 | 16 | describe DocumentIdentifier do 17 | it 'should fail as a hash key' do 18 | hash = {} ##(simple 19 | document = Document.new( 'cia', 'Roswell', 'story' ) 20 | first_id = DocumentIdentifier.new( 'public', 'CoverStory' ) 21 | 22 | hash[first_id] = document ##simple) 23 | 24 | 25 | hash[first_id].equal?(document).should == true 26 | 27 | second_id = DocumentIdentifier.new( 'docs/public', 'CoverStory' ) ##(id2 28 | the_doc_again = hash[second_id] ##id2) 29 | 30 | the_doc_again.should == nil 31 | end 32 | end 33 | 34 | -------------------------------------------------------------------------------- /12/known_words.txt: -------------------------------------------------------------------------------- 1 | object_id 2 | >= 3 | -------------------------------------------------------------------------------- /13/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /13/ex_3_uri_spec.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | 3 | describe 'uri class methods' do 4 | 5 | it 'should work like the books says' do 6 | require 'uri' ##(inst 7 | 8 | google = URI.parse( 'http://www.google.com' ) 9 | 10 | puts google.scheme # prints 'http' 11 | puts google.host # prints 'www.google.com' ##inst) 12 | 13 | pp URI.scheme_list ##+class 14 | end 15 | end 16 | 17 | 18 | -------------------------------------------------------------------------------- /13/ex_4_date_spec.rb: -------------------------------------------------------------------------------- 1 | require 'date' 2 | 3 | describe Date do 4 | it 'should have a civil method' do 5 | require 'date' ##(civil 6 | xmas = Date.civil( 2010, 12, 25 ) ##civil) 7 | p xmas.to_s 8 | end 9 | 10 | it 'should have an ordinal method' do 11 | xmas = Date.ordinal( 2010, 359 ) ##+ord 12 | p xmas.to_s 13 | end 14 | 15 | it 'should have a commercial method' do 16 | xmas = Date.commercial( 2010, 51, 6 ) ##+com 17 | p xmas.to_s 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /13/ex_examples2_spec.rb: -------------------------------------------------------------------------------- 1 | class Document ##(main 2 | class << self 3 | def find_by_name( name ) 4 | # Find a document by name... 5 | end 6 | 7 | def find_by_id( doc_id ) 8 | # Find a document by id 9 | end 10 | end 11 | end ##main) 12 | 13 | describe Document do 14 | it "should have the singleton methods" do 15 | Document.find_by_name( 'doc' ) 16 | Document.find_by_id( '124' ) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /13/ex_examples3_spec.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | 3 | describe "Singleton methods in stubs" do ##(main 4 | it "is just a demonstration of stubs as singleton methods" do 5 | stub_printer = stub :available? => true, :render => nil 6 | pp stub_printer.singleton_methods 7 | stub_printer.singleton_methods.should include(:available?) ##--main 8 | stub_printer.singleton_methods.should include(:render) ##--main 9 | end 10 | end ##main) 11 | -------------------------------------------------------------------------------- /13/ex_examples4_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(doc 4 | def self.create_test_document( length ) 5 | Document.new( 'test', 'test', 'test ' * length ) 6 | end 7 | 8 | # ... 9 | end ##doc) 10 | 11 | describe Document do 12 | it 'should have a create_test_document method' do 13 | book = Document.create_test_document( 10000 ) ##+good 14 | 15 | lambda { 16 | longer_doc = book.create_test_document( 20000 ) ##+bad 17 | }.should raise_error(NoMethodError) 18 | 19 | longer_doc = book.class.create_test_document( 20000 ) ##+fixed 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /13/ex_examples5_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | class Parent ##(main 4 | def self.who_am_i 5 | puts "The value of self is #{self}" 6 | end 7 | end 8 | 9 | class Child < Parent 10 | end ##main) 11 | 12 | describe Child do 13 | it 'should output the child class name' do 14 | out = output_of { Parent.who_am_i } 15 | out.should match(/Parent/) 16 | out = output_of { Child.who_am_i } 17 | out.should match(/Child/) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /13/mocha_demo.rb: -------------------------------------------------------------------------------- 1 | require 'mocha' 2 | 3 | include Mocha::API 4 | 5 | class Document 6 | end 7 | 8 | mock_doc = Document.new 9 | mock_doc.expects(:words).returns( %w{Call me Ishmael} ) 10 | mock_doc.expects(:word_count).returns( 3 ) 11 | p mock_doc.singleton_methods 12 | -------------------------------------------------------------------------------- /13/t1.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require 'mocha' 3 | 4 | class Product 5 | def self.find(n) 6 | end 7 | end 8 | 9 | class MiscExampleTest < Test::Unit::TestCase 10 | 11 | def test_mocking_a_class_method 12 | product = Product.new 13 | Product.expects(:find).with(1).returns(product) 14 | #assert_equal product, Product.find(1) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /13/telling.txt: -------------------------------------------------------------------------------- 1 | I'm not telling 2 | -------------------------------------------------------------------------------- /14/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /14/document_with_accessor_iv.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | @default_font = :times 6 | 7 | class << self 8 | attr_accessor :default_font 9 | end 10 | 11 | # Rest of the class omitted... 12 | end ##main) 13 | 14 | class Document 15 | 16 | attr_accessor :font 17 | 18 | def initialize(title, author) 19 | @title = title 20 | @author = author 21 | @font = Document.default_font 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /14/document_with_cv.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | @@default_paper_size = :a4 6 | 7 | def self.default_paper_size 8 | @@default_paper_size 9 | end 10 | 11 | def self.default_paper_size=(new_size) 12 | @@default_paper_size = new_size 13 | end 14 | 15 | attr_accessor :title, :author, :content 16 | attr_accessor :paper_size 17 | 18 | def initialize(title, author, content) 19 | @title = title 20 | @author = author 21 | @content = content 22 | @paper_size = @@default_paper_size 23 | end 24 | 25 | # Rest of the class omitted... 26 | end ##main) 27 | -------------------------------------------------------------------------------- /14/document_with_default_font.rb: -------------------------------------------------------------------------------- 1 | require 'document_with_cv' 2 | 3 | 4 | class Document ##(main 5 | @@default_font = :times 6 | 7 | # Rest of the class omitted... 8 | end ##main) 9 | 10 | class Document 11 | def self.default_font=(font) 12 | @@default_font = font 13 | end 14 | 15 | 16 | def self.default_font 17 | @@default_font 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /14/document_with_iv.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(iv 4 | 5 | @default_font = :times 6 | 7 | def self.default_font=(font) 8 | @default_font = font 9 | end 10 | 11 | def self.default_font 12 | @default_font 13 | end 14 | 15 | # Rest of the class omitted... 16 | end ##iv) 17 | 18 | class Document 19 | 20 | attr_accessor :font 21 | 22 | def initialize(title, author) ##(init 23 | @title = title 24 | @author = author 25 | @font = Document.default_font 26 | end ##init) 27 | 28 | end 29 | -------------------------------------------------------------------------------- /14/document_with_iv_examples.rb: -------------------------------------------------------------------------------- 1 | describe Document do 2 | 3 | it 'should start with a default paper size' do 4 | Document.default_font.should == :times 5 | Document.default_font = :dingbat 6 | Document.default_font.should == :dingbat 7 | end 8 | 9 | it 'should pass on the default font to the subclases' do 10 | d = Document.new( 'example', 'russ' ) 11 | d.font.should == Document.default_font 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /14/document_with_silly_instance_variable_spec.rb: -------------------------------------------------------------------------------- 1 | class Document ##(main 2 | attr_accessor :default_font 3 | end ##main) 4 | 5 | 6 | describe Document do 7 | it 'should have a default font instance var' do 8 | doc = Document.new 9 | doc.default_font = 'foo' 10 | doc.default_font.should == 'foo' 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /14/ex_1_document_with_cv_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'document_with_cv' 3 | 4 | describe Document do 5 | 6 | it 'should start with a default paper size' do 7 | Document.default_paper_size.should == :a4 8 | Document.default_paper_size = :us_letter 9 | Document.default_paper_size.should == :us_letter 10 | end 11 | 12 | end 13 | -------------------------------------------------------------------------------- /14/ex_3_doc_disaster_spec.rb: -------------------------------------------------------------------------------- 1 | require 'document_with_default_font' 2 | require 'presentation' 3 | require 'resume' 4 | 5 | require 'pp' 6 | 7 | describe 'Document and subclasses fighting' do 8 | 9 | it 'Document has the only class variable' do 10 | Document.class_variable_defined?(:@@default_font).should == true 11 | Document.default_font.should == :arial # from resume 12 | Resume.default_font.should == :arial 13 | Presentation.default_font.should == :arial 14 | 15 | Resume.default_font = :for_resume 16 | Document.default_font.should == :for_resume 17 | Resume.default_font.should == :for_resume 18 | Presentation.default_font.should == :for_resume 19 | 20 | Presentation.default_font = :for_pres 21 | Document.default_font.should == :for_pres 22 | Resume.default_font.should == :for_pres 23 | Presentation.default_font.should == :for_pres 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /14/ex_4_more_doc_disaster_spec.rb: -------------------------------------------------------------------------------- 1 | require 'document_with_default_font' 2 | require 'resume' 3 | require 'presentation' 4 | 5 | 6 | 7 | describe 'Loading presentation last changes global def font' do 8 | 9 | it 'Document has the only class variable' do 10 | Document.class_variable_defined?(:@@default_font).should == true 11 | Document.default_font.should == :nimbus 12 | Resume.default_font.should == :nimbus 13 | Presentation.default_font.should == :nimbus 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /14/ex_5_document_with_iv_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'document_with_iv' 3 | 4 | require 'document_with_iv_examples' 5 | -------------------------------------------------------------------------------- /14/ex_6_document_with_accessor_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'document_with_accessor_iv' 3 | 4 | require 'document_with_iv_examples' 5 | -------------------------------------------------------------------------------- /14/ex_8_wild.rb: -------------------------------------------------------------------------------- 1 | require 'uri' 2 | 3 | describe URI do 4 | 5 | it 'should work like the book says' do 6 | my_uri = URI.parse('http://www.russolsen.com') ##+uri 7 | my_uri.host.should == 'www.russolsen.com' 8 | my_uri.scheme.should == 'http' 9 | my_url.port.should == 80 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /14/presentation.rb: -------------------------------------------------------------------------------- 1 | class Presentation < Document 2 | @@default_font = :nimbus 3 | 4 | def self.default_font=(font) 5 | @@default_font = font 6 | end 7 | 8 | 9 | def self.default_font 10 | @@default_font 11 | end 12 | 13 | attr_accessor :font 14 | 15 | def initialize 16 | @font = @@default_font 17 | end 18 | 19 | # Rest of the class omitted... 20 | end 21 | 22 | -------------------------------------------------------------------------------- /14/resume.rb: -------------------------------------------------------------------------------- 1 | class Resume < Document 2 | @@default_font = :arial 3 | 4 | def self.default_font=(font) 5 | @@default_font = font 6 | end 7 | 8 | 9 | def self.default_font 10 | @@default_font 11 | end 12 | 13 | attr_accessor :font 14 | 15 | 16 | def initialize 17 | @font = @@default_font 18 | end 19 | 20 | # Rest of the class omitted... 21 | end 22 | -------------------------------------------------------------------------------- /14/resume_presentation_with_iv.rb: -------------------------------------------------------------------------------- 1 | require 'document_with_accessor_iv' 2 | 3 | class Presentation < Document ##(pres 4 | 5 | @default_font = :nimbus 6 | 7 | class << self 8 | attr_accessor :default_font 9 | end 10 | 11 | def initialize(title, author) 12 | @title = title 13 | @author = author 14 | @font = Presentation.default_font 15 | end 16 | 17 | # most of the class omitted... 18 | end ##pres) 19 | 20 | class Resume < Document ##(resume 21 | 22 | @default_font = :arial 23 | 24 | class << self 25 | attr_accessor :default_font 26 | end 27 | 28 | def initialize(title, author) 29 | @title = title 30 | @author = author 31 | @font = Presentation.default_font 32 | end 33 | 34 | # most of the class omitted... 35 | end ##resume) 36 | 37 | -------------------------------------------------------------------------------- /15/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /15/demo_bit_at_a_time.rb: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | module Rendering 4 | class Font 5 | def initialize( name, weight=:normal, size=10 ) 6 | end 7 | end 8 | 9 | class PaperSize 10 | def initialize( name='US Let', width=8.5, height=11.0 ) 11 | end 12 | end 13 | end 14 | 15 | 16 | module Rendering ##(bit_font 17 | class Font 18 | # Bulk of class omitted... 19 | end 20 | 21 | DEFAULT_FONT = Font.new( 'default' ) 22 | end ##bit_font) 23 | 24 | module Rendering ##(bit_paper 25 | class PaperSize 26 | # Bulk of class omitted... 27 | end 28 | 29 | DEFAULT_PAPER_SIZE = PaperSize.new 30 | end ##bit_paper) 31 | 32 | raise "failed" unless Rendering::Font.instance_of?(Class) 33 | raise "failed" unless Rendering::DEFAULT_FONT.instance_of?(Rendering::Font) 34 | 35 | raise "failed" unless Rendering::PaperSize.instance_of?(Class) 36 | raise "failed" unless Rendering::DEFAULT_PAPER_SIZE.instance_of?(Rendering::PaperSize) 37 | 38 | -------------------------------------------------------------------------------- /15/ex_print_papersize_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ex_rendering' 2 | 3 | include Rendering ##(main 4 | 5 | puts "The default paper height is #{DEFAULT_PAPER_SIZE.height}" ##main) 6 | 7 | -------------------------------------------------------------------------------- /15/ex_rendering.rb: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | module Rendering ##(basic 4 | class Font 5 | attr_accessor :name, :weight, :size 6 | 7 | def initialize( name, weight=:normal, size=10 ) 8 | @name = name 9 | @weight = weight 10 | @size = size 11 | end 12 | 13 | # Rest of the class omitted... 14 | end 15 | 16 | class PaperSize 17 | attr_accessor :name, :width, :height 18 | 19 | def initialize( name='US Let', width=8.5, height=11.0 ) 20 | @name = name 21 | @width = width 22 | @height = height 23 | end 24 | # Rest of the class omitted... 25 | end 26 | end ##basic) 27 | 28 | module Rendering ##(const 29 | # Font and PaperSize classes omitted... 30 | 31 | DEFAULT_FONT = Font.new( 'default' ) 32 | DEFAULT_PAPER_SIZE = PaperSize.new 33 | end ##const) 34 | 35 | -------------------------------------------------------------------------------- /15/ex_wp_points_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'wp_points' 3 | 4 | describe WordProcessor do 5 | 6 | it "should have points conversion methods" do 7 | WordProcessor.points_to_inches( 72.0 ).should == 1.0 8 | WordProcessor.points_to_inches( 720.0 ).should == 10.0 9 | an_inch_full_of_points = WordProcessor.inches_to_points( 1.0 ) ##+main 10 | an_inch_full_of_points.should == 72.0 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /15/known_words.txt: -------------------------------------------------------------------------------- 1 | Date 2 | DataMapper 3 | -------------------------------------------------------------------------------- /15/mod_printer_classes.rb: -------------------------------------------------------------------------------- 1 | module TonsOToner ##(tot 2 | class PrintQueue 3 | def submit( print_job ) 4 | # Send the job off for printing to this laser printer 5 | end 6 | 7 | def cancel( print_job) 8 | # Stop! 9 | end 10 | end 11 | 12 | class Administration 13 | def power_off 14 | # Turn this laser printer off... 15 | end 16 | 17 | def start_self_test 18 | # Everything ok? 19 | end 20 | end 21 | end ##tot) 22 | 23 | 24 | module OceansOfInk ##(ooi 25 | class PrintQueue 26 | def submit( print_job ) 27 | # Send the job off for printing to this ink jet printer 28 | end 29 | # Rest omitted... 30 | end 31 | 32 | class Administration 33 | # Ink jet administration code omitted... 34 | end 35 | end ##ooi) 36 | -------------------------------------------------------------------------------- /15/printer_classes.rb: -------------------------------------------------------------------------------- 1 | class TonsOTonerPrintQueue 2 | def submit( print_job ) 3 | # Send the job off for printing to this laser printer... 4 | end 5 | 6 | def cancel( print_job) 7 | # Stop the print job on this laser printer... 8 | end 9 | end 10 | 11 | class TonsOTonerAdministration 12 | def power_off 13 | # Turn this laser printer off... 14 | end 15 | 16 | def start_self_test 17 | # Test this laser printer... 18 | end 19 | end 20 | 21 | class OceansOfInkPrintQueue 22 | def submit( print_job ) 23 | # Send the job off for printing to this ink jet printer... 24 | end 25 | 26 | def cancel( print_job) 27 | # Stop the print job on this ink jet printer... 28 | end 29 | end 30 | 31 | Class OceansOfInkAdministration 32 | def power_off 33 | # Turn this ink jet printer off... 34 | end 35 | 36 | def start_self_test 37 | # Test this ink jet printer... 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /15/trouble_mod_bad.rb: -------------------------------------------------------------------------------- 1 | module WordProcessor 2 | 3 | def points_to_inches( points ) 4 | points / 72.0 5 | end 6 | 7 | # etc... 8 | end 9 | 10 | -------------------------------------------------------------------------------- /15/trouble_mod_bad_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'trouble_mod_bad' 3 | include WordProcessor 4 | 5 | describe WordProcessor do 6 | 7 | it "should have instance points conversion methods" do 8 | points_to_inches( 72.0 ).should == 1.0 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /15/trouble_mod_good.rb: -------------------------------------------------------------------------------- 1 | module WordProcessor 2 | 3 | def self.points_to_inches( points ) 4 | points / 72.0 5 | end 6 | 7 | # etc... 8 | end 9 | -------------------------------------------------------------------------------- /15/trouble_mod_good_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'trouble_mod_good' 3 | 4 | describe WordProcessor do 5 | 6 | it "should have points conversion methods" do 7 | WordProcessor.points_to_inches( 72.0 ).should == 1.0 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /15/word_processor.rb: -------------------------------------------------------------------------------- 1 | module WordProcessor 2 | module Rendering 3 | class Font 4 | # Guts of class omitted... 5 | end 6 | 7 | # and so on... 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /15/word_processor_spec.rb: -------------------------------------------------------------------------------- 1 | require 'word_processor' 2 | 3 | describe WordProcessor do 4 | 5 | it "should have a Font class" do 6 | WordProcessor.should be_an_instance_of( Module ) 7 | WordProcessor::Rendering.should be_an_instance_of( Module ) 8 | WordProcessor::Rendering::Font.should be_an_instance_of( Class ) 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /15/wp_points.rb: -------------------------------------------------------------------------------- 1 | module WordProcessor 2 | 3 | def self.points_to_inches( points ) 4 | points / 72.0 5 | end 6 | 7 | def self.inches_to_points( inches ) 8 | inches * 72.0 9 | end 10 | 11 | # Rest of the module omitted 12 | end 13 | -------------------------------------------------------------------------------- /16/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /16/electronic_text.rb: -------------------------------------------------------------------------------- 1 | class ElectronicText ##(text 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize( title, author, content ) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | end ##text) 10 | 11 | class ElectronicBook < ElectronicText ##(book 12 | # Lots of complicated stuff omitted... 13 | end ##book) 14 | -------------------------------------------------------------------------------- /16/ex_1_doc_with_method_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | CLICHES = [ /play fast and loose/, 6 | /make no mistake/, 7 | /does the trick/, 8 | /off and running/, 9 | /my way or the highway/ ] 10 | 11 | def number_of_cliches 12 | CLICHES.inject(0) do |count, phrase| 13 | count += 1 if phrase =~ content 14 | count 15 | end 16 | end 17 | 18 | # Rest of the class omitted... 19 | end ##main) 20 | 21 | require 'prose_quality_examples' 22 | -------------------------------------------------------------------------------- /16/ex_3_prose_quality_mixin_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require 'electronic_text' 3 | require 'writing_quality_mixin' 4 | 5 | class Document ##(wq_mixin_classes 6 | include WritingQuality 7 | 8 | # Lots of stuff omitted... 9 | end 10 | 11 | class ElectronicBook < ElectronicText 12 | include WritingQuality 13 | 14 | # Lots of stuff omitted... 15 | end ##wq_mixin_classes) 16 | 17 | require 'prose_quality_examples' 18 | 19 | describe 'Document and ebook' do 20 | it 'should have working examples' do 21 | text = "my way or the highway does the trick" ##(doc_demo 22 | my_tome = Document.new('Hackneyed', 'Russ', text) 23 | puts my_tome.number_of_cliches ##doc_demo) 24 | 25 | my_ebook = ElectronicBook.new( 'EHackneyed', 'Russ', text) ##(ebook_demo 26 | puts my_ebook.number_of_cliches ##ebook_demo) 27 | 28 | my_tome.number_of_cliches.should == 2 29 | my_ebook.number_of_cliches.should == 2 30 | end 31 | end 32 | 33 | 34 | -------------------------------------------------------------------------------- /16/ex_4_multiple_modules_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require 'electronic_text' 3 | require 'writing_quality_mixin' 4 | 5 | module ProjectManagement 6 | def proj_man 7 | end 8 | end 9 | 10 | module AuthorAccountTracking 11 | def author_account 12 | end 13 | end 14 | 15 | module ProjectManagement ##(more_mods 16 | # Lots of boring stuff omitted 17 | end 18 | 19 | module AuthorAccountTracking 20 | # Lots of even more boring stuff omitted 21 | end 22 | 23 | class ElectronicBook < ElectronicText 24 | include WritingQuality 25 | include ProjectManagement 26 | include AuthorAccountTracking 27 | 28 | # Lots of stuff omitted... 29 | end ##more_mods) 30 | 31 | describe ElectronicBook do 32 | it 'should have all the methods from all the modules' do 33 | eb = ElectronicBook.new( 'test', 'russ', 'hello' ) 34 | eb.number_of_cliches.should == 0 35 | lambda { eb.proj_man }.should_not raise_error 36 | lambda { eb.author_account }.should_not raise_error 37 | end 38 | end 39 | 40 | -------------------------------------------------------------------------------- /16/ex_5_class_mixin_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | module Finders ##(finders 4 | def find_by_name( name ) 5 | # Find a document by name... 6 | end 7 | 8 | def find_by_id( doc_id ) 9 | # Find a document by id 10 | end 11 | end ##finders) 12 | 13 | 14 | class Document ##(inc_doc 15 | # Most of the class omitted... 16 | 17 | class << self 18 | include Finders 19 | end 20 | end ##inc_doc) 21 | 22 | describe 'document with finders' do 23 | it 'should have the right methods' do 24 | war_and_peace = Document.find_by_name( 'War And Peace' ) ##+war_and_peace 25 | war_and_peace = Document.find_by_name( '0123456' ) 26 | end 27 | end 28 | 29 | -------------------------------------------------------------------------------- /16/ex_6_class_extend_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | module Finders 4 | def find_by_name( name ) 5 | # Find a document by name... 6 | end 7 | 8 | def find_by_id( doc_id ) 9 | # Find a document by id 10 | end 11 | end 12 | 13 | 14 | class Document ##(extend 15 | extend Finders 16 | 17 | # Most of the class omitted... 18 | end ##extend) 19 | 20 | 21 | describe 'document with finders' do 22 | it 'should have the right methods' do 23 | war_and_peace = Document.find_by_name( 'War And Peace' ) 24 | war_and_peace = Document.find_by_name( '0123456' ) 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /16/ex_7_override_with_local_method_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | require 'writing_quality_mixin' 4 | 5 | 6 | class Document ##(override 7 | include WritingQuality 8 | 9 | # Rest of the class omitted... 10 | end 11 | 12 | class PoliticalBook < Document 13 | def number_of_cliches 14 | 0 15 | end 16 | 17 | # Rest of the class omitted... 18 | end ##override) 19 | 20 | describe PoliticalBook do 21 | it 'should always report zero cliches' do 22 | text = "my way or the highway does the trick" 23 | pb = PoliticalBook.new( 'speech', 'russ', text) 24 | pb.number_of_cliches.should == 0 25 | doc = Document.new( 'speech', 'russ', text) 26 | doc.number_of_cliches.should == 2 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /16/ex_8_override_with_another_module_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require 'writing_quality_mixin' 3 | 4 | 5 | module PoliticalWritingQuality ##(pwq 6 | # No phrase is too worn out to be a cliché 7 | # in political writing 8 | def number_of_cliches 9 | 0 10 | end 11 | end ##pwq) 12 | 13 | class Document 14 | include WritingQuality 15 | 16 | # Rest of the class omitted... 17 | end 18 | 19 | class PoliticalBook < Document ##(pb 20 | include WritingQuality 21 | include PoliticalWritingQuality 22 | 23 | # Lots of stuff omitted... 24 | end ##pb) 25 | 26 | describe PoliticalBook do 27 | it 'should always report zero cliches' do 28 | text = "my way or the highway does the trick" 29 | pb = PoliticalBook.new( 'speech', 'russ', text) 30 | pb.number_of_cliches.should == 0 31 | doc = Document.new( 'speech', 'russ', text) 32 | doc.number_of_cliches.should == 2 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /16/prose_quality_examples.rb: -------------------------------------------------------------------------------- 1 | describe Document do 2 | 3 | it 'should report 0 cliches for a doc w/o cliches' do 4 | d = Document.new( 'no cliche', 'russ', 'This is original' ) 5 | d.number_of_cliches.should == 0 6 | end 7 | 8 | it 'should report 0 cliches for a empty doc' do 9 | d = Document.new( 'no cliche', 'russ', '' ) 10 | d.number_of_cliches.should == 0 11 | end 12 | 13 | it 'should report 1 cliches for a doc with 1 cliches' do 14 | d = Document.new( 'no cliche', 'russ', 'We need to make no mistake' ) 15 | d.number_of_cliches.should == 1 16 | end 17 | 18 | it 'should report 3 cliches for a doc with 3 cliches' do 19 | content = 'does the trick my way or the highway off and running' 20 | d = Document.new( 'no cliche', 'russ', content ) 21 | d.number_of_cliches.should == 3 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /16/writing_quality_mixin.rb: -------------------------------------------------------------------------------- 1 | module WritingQuality ##(main 2 | 3 | CLICHES = [ /play fast and loose/, 4 | /make no mistake/, 5 | /does the trick/, 6 | /off and running/, 7 | /my way or the highway/ ] 8 | 9 | def number_of_cliches ##(noc 10 | CLICHES.inject(0) do |count, phrase| 11 | count += 1 if phrase =~ content 12 | count 13 | end 14 | end ##noc) 15 | end ##main) 16 | -------------------------------------------------------------------------------- /17/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | 3 | CLEAN.include(%w{choc.txt donuts.txt pi4.txt}) 4 | CLEAN.include(%w{sorted_chars.txt with_arg.txt resolv.txt}) 5 | 6 | -------------------------------------------------------------------------------- /17/doc_each_word.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | 3 | # Stuff omitted... 4 | 5 | def each_word ##(main 6 | words.each { |word| yield( word ) } 7 | end ##main) 8 | end 9 | -------------------------------------------------------------------------------- /17/doc_with_each_char.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | def each_character 3 | index = 0 4 | while index < @content.size 5 | yield( @content[index] ) 6 | index += 1 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /17/ex_2_basic_doc_iterator_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/doc3' 3 | require '../utils/rspec_utils' 4 | 5 | class Document ##(main 6 | 7 | # Stuff omitted... 8 | 9 | def each_word 10 | word_array = words 11 | index = 0 12 | while index < words.size 13 | yield( word_array[index] ) 14 | index += 1 15 | end 16 | end 17 | end ##main) 18 | 19 | describe Document do 20 | it 'should have a good each_word method' do 21 | out = output_of { 22 | d = Document.new( 'Truth', 'Gump', 'Life is like a box of ...' ) ##(example 23 | d.each_word {|word| puts word} ##example) 24 | } 25 | out.should match( /Life\nis\nlike\n.*/m) 26 | File.write( 'choc.txt', out ) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /17/ex_3_easy_doc_iterator_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/doc3' 3 | require '../utils/rspec_utils' 4 | require 'doc_each_word' 5 | 6 | describe Document do 7 | it 'should have a good each_word method' do 8 | d = Document.new( 'Truth', 'Gump', 'Life is like a box of chocolates' ) 9 | out = output_of { 10 | d.each_word {|word| puts word} 11 | } 12 | out.should match( /Life\nis\nlike\n.*choc.*/m) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /17/ex_4_each_char_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | 4 | 5 | class Document ##(main 6 | 7 | # Stuff omitted 8 | 9 | def each 10 | # iterate over the words as in our first example 11 | end 12 | 13 | def each_character 14 | # iterate over the characters 15 | end 16 | end ##main) 17 | 18 | 19 | require 'doc_with_each_char' 20 | 21 | 22 | describe Document do 23 | it 'should have a good each_character method' do 24 | d = Document.new( 'Truth', 'Gump', 'Life is like a box of chocolates' ) 25 | out = output_of { 26 | d.each_character {|ch| puts ch} 27 | } 28 | out.should match( /L\ni\nf\n.*e\ns\n/m) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /17/ex_5_each_word_pair_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | 4 | 5 | class Document ##(pair 6 | # Most of the class omitted... 7 | 8 | def each_word_pair 9 | word_array = words 10 | index = 0 11 | while index < (word_array.size-1) 12 | yield word_array[index], word_array[index+1] 13 | index += 1 14 | end 15 | end 16 | end ##pair) 17 | 18 | describe Document do 19 | it 'should have a good each_word_pair method' do 20 | out = output_of { 21 | doc = Document.new('Donuts', '?', 'I love donuts mmmm donuts' ) ##(donuts 22 | doc.each_word_pair{ |first, second| puts "#{first} #{second}" } ##donuts) 23 | } 24 | out.should match( /I love\nlove donuts\ndonuts mmmm\nmmmm donuts\n/m ) 25 | File.write( 'donuts.txt', out ) 26 | end 27 | end 28 | 29 | 30 | describe "The times method" do 31 | it 'should work as advertised' do 32 | 12.times { |x| puts "The number is #{x}" } ##+times 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /17/ex_7_enumerator_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | require 'doc_with_each_char' 4 | require 'pp' 5 | 6 | describe Document do 7 | it 'should work with enum' do 8 | doc = Document.new('example', 'russ', "We are all characters") ##(main 9 | enum = doc.enum_for(:each_character ) ##main) 10 | 11 | a = enum.to_a 12 | a[0].should == 'W' 13 | a[1].should == 'e' 14 | a.last.should == 's' 15 | 16 | sorted = enum.sort 17 | sorted[0].should == ' ' 18 | sorted[3].should == 'W' 19 | 20 | output_of { 21 | puts enum.count ##+count 22 | }.should == "21\n" 23 | 24 | out = output_of { 25 | pp enum.sort ##+sort 26 | } 27 | File.write( 'sorted_chars.txt', out ) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /17/ex_8_trouble.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | 4 | class Document 5 | def each_word 6 | word_array = words 7 | index = 0 8 | while index < words.size 9 | yield( word_array[index] ) 10 | index += 1 11 | end 12 | end 13 | end 14 | 15 | describe 'iterators and exceptions' do 16 | it 'should stop the iterator' do 17 | doc = Document.new('example', 'russ', "a b c now d") 18 | 19 | lambda { 20 | doc.each_word do |word| ##(boom 21 | raise 'boom' if word == 'now' 22 | end ##boom) 23 | }.should raise_error 24 | 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /17/ex_8c_break_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require 'doc_each_word' 3 | 4 | def count_till_tuesday( doc ) ##(main 5 | count = 0 6 | doc.each_word do |word| 7 | count += 1 8 | break if word == 'Tuesday' 9 | end 10 | count ##main) 11 | end 12 | 13 | 14 | describe 'each_word method with break' do 15 | 16 | it 'should work exit the calling method' do 17 | doc = Document.new( 'whatever', 'russ', 'Monday Tuesday Wed' ) 18 | count_till_tuesday( doc ).should == 2 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /17/ex_9_real_world_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require 'resolv' 3 | 4 | describe Dir do 5 | it 'should run thru the files in a dir' do 6 | puts "Contents of /etc directory:" ##(dir 7 | etc_dir = Dir.new("/etc") 8 | etc_dir.each {|entry| puts entry} ##dir) 9 | end 10 | end 11 | 12 | describe Resolv do 13 | it 'should go thru the inet addresses' do 14 | out = output_of { 15 | Resolv.each_address( "www.google.com" ) {|a| puts a} ##+addr 16 | } 17 | File.write( 'resolv.txt', out ) 18 | end 19 | end 20 | 21 | describe ObjectSpace do 22 | it 'should have an each_object method' do 23 | output_of { 24 | ObjectSpace.each_object(String) { |the_string| puts the_string } ##+obj 25 | } 26 | end 27 | end 28 | 29 | describe 'Prime' do 30 | it 'should have an each method' do 31 | require 'mathn' 32 | # Warning: According to Euclid, this never stops... 33 | Prime.each {|x| break if x > 100 } 34 | end 35 | end 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /18/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /18/doc_with_load_save.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Logger 4 | end 5 | 6 | class Document 7 | 8 | class << self 9 | attr_accessor :load_fail, :save_fail 10 | end 11 | 12 | def self.load( path ) 13 | raise 'document failed' if @load_fail 14 | new( path, 'russ', '' ) 15 | end 16 | 17 | def save 18 | raise 'document failed' if self.class.save_fail 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /18/ex_1_simple_load_save_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_with_load_save' 2 | 3 | class SomeApplication ##(main 4 | # ... 5 | 6 | def do_something 7 | doc = Document.load( 'resume.txt' ) 8 | 9 | # Do something interesting with the document. 10 | 11 | doc.save 12 | end 13 | end ##main) 14 | 15 | 16 | describe SomeApplication do 17 | it 'should just work' do 18 | SomeApplication.new.do_something 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /18/ex_2_simple_with_logging_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_with_load_save' 2 | 3 | 4 | class SomeApplication ##(main 5 | 6 | def initialize( logger ) 7 | @logger = logger 8 | end 9 | 10 | def do_something 11 | @logger.debug( 'Starting Document load' ) 12 | doc = Document.load( 'resume.txt' ) 13 | @logger.debug( 'Completed Document load' ) 14 | 15 | # Do something interesting with the document. 16 | 17 | @logger.debug( 'Starting Document save' ) 18 | doc.save 19 | @logger.debug( 'Completed Document save' ) 20 | end 21 | end ##main) 22 | 23 | describe SomeApplication do 24 | 25 | before :each do 26 | Document.load_fail = Document.save_fail = false 27 | end 28 | 29 | it 'should work' do 30 | logger = mock 31 | logger.should_receive( :debug ).exactly(4).times 32 | SomeApplication.new( logger ).do_something 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /18/ex_3_load_save_with_logging_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_with_load_save' 2 | 3 | 4 | class SomeApplication ##(main 5 | 6 | # Rest of the class omitted... 7 | 8 | def do_something 9 | begin 10 | @logger.debug( 'Starting Document load' ) 11 | @doc = Document.load( 'resume.txt' ) 12 | @logger.debug( 'Completed Document load' ) 13 | rescue 14 | @logger.error( 'Load failed!!' ) 15 | raise 16 | end 17 | 18 | # Do something with the document... 19 | 20 | begin 21 | @logger.debug( 'Starting Document save' ) 22 | @doc.save 23 | @logger.debug( 'Completed Document save' ) 24 | rescue 25 | @logger.error( 'Save failed!!' ) 26 | raise 27 | end 28 | end 29 | end ##main) 30 | 31 | 32 | class SomeApplication 33 | 34 | def initialize( logger ) 35 | @logger = logger 36 | end 37 | end 38 | 39 | load 'some_application_examples.rb' 40 | -------------------------------------------------------------------------------- /18/ex_6_degenerative_xaround_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | class SomeApplication 3 | def log_before( description ) ##(before 4 | @logger.debug( "Starting #{description}" ) 5 | yield 6 | end ##before) 7 | 8 | 9 | def log_after( description ) ##(after 10 | yield 11 | @logger.debug( "Done #{description}" ) 12 | end ##after) 13 | end 14 | 15 | class SomeApplication 16 | def initialize( logger ) 17 | @logger = logger 18 | end 19 | end 20 | 21 | describe SomeApplication do 22 | 23 | it 'should have a propert log_before' do 24 | logger = mock 25 | logger.should_receive(:debug).exactly(1).times 26 | SomeApplication.new(logger).log_before('test') {} 27 | end 28 | 29 | it 'should have a propert log_after' do 30 | logger = mock 31 | logger.should_receive(:debug).exactly(1).times 32 | SomeApplication.new(logger).log_after('test') {} 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /18/ex_8_bogus_object_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'doc_with_load_save' 3 | 4 | class SomeApplication ##(main 5 | 6 | # Rest of the class omitted... 7 | 8 | def do_something 9 | with_logging('load', nil) { @doc = Document.load( 'book' ) } 10 | 11 | # Do something with the document... 12 | 13 | with_logging('save', @doc) { |the_object| the_object.save } 14 | end 15 | 16 | 17 | def with_logging(description, the_object) 18 | begin 19 | @logger.debug( "Starting #{description}" ) 20 | yield( the_object ) 21 | @logger.debug( "Completed #{description}" ) 22 | rescue 23 | @logger.error( "#{description} failed!!") 24 | raise 25 | end 26 | end 27 | end ##main) 28 | 29 | 30 | class SomeApplication 31 | def initialize( logger ) 32 | @logger = logger 33 | end 34 | end 35 | 36 | 37 | load 'some_application_examples.rb' 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /18/ex_8a_with_database_spec.rb: -------------------------------------------------------------------------------- 1 | class Database 2 | end 3 | 4 | 5 | class SomeApplication 6 | def with_database_connection( connection_info ) ##(main 7 | connection = Database.new( connection_info ) 8 | begin 9 | yield( connection ) 10 | ensure 11 | connection.close 12 | end 13 | end ##main) 14 | end 15 | 16 | describe SomeApplication do 17 | 18 | it 'should create and close a new database connection' do 19 | connection = mock 20 | connection.should_receive(:close) 21 | connection.should_receive(:query) 22 | Database.should_receive(:new).with('info').and_return(connection) 23 | 24 | app = SomeApplication.new 25 | app.with_database_connection('info') {|c| c.query} 26 | end 27 | end 28 | 29 | -------------------------------------------------------------------------------- /18/ex_9_return_value_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_with_load_save' 2 | 3 | 4 | class SomeApplication 5 | 6 | # Rest of the class omitted... 7 | 8 | def with_logging(description) ##(main 9 | begin 10 | @logger.debug( "Starting #{description}" ) 11 | return_value = yield 12 | @logger.debug( "Completed #{description}" ) 13 | return_value 14 | rescue 15 | @logger.error( "#{description} failed!!") 16 | raise 17 | end 18 | end ##main) 19 | end 20 | 21 | class SomeApplication 22 | def initialize( logger ) 23 | @logger = logger 24 | end 25 | end 26 | 27 | 28 | describe SomeApplication do 29 | it "should have a working silly method" do 30 | logger = mock 31 | logger.should_receive(:debug).exactly(2).times 32 | SomeApplication.new(logger).with_logging('42') { 42 }.should == 42 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /18/some_application_examples.rb: -------------------------------------------------------------------------------- 1 | describe SomeApplication do 2 | 3 | before :each do 4 | Document.load_fail = Document.save_fail = false 5 | end 6 | 7 | it 'should do the proper logging when no exceptions are raised' do 8 | logger = mock 9 | logger.should_receive(:debug).exactly(4).times 10 | SomeApplication.new(logger).do_something 11 | end 12 | 13 | it 'should do the proper logging when the save fails' do 14 | logger = mock 15 | logger.should_receive(:debug).exactly(3).times 16 | logger.should_receive(:error).once 17 | Document.save_fail = true 18 | lambda { SomeApplication.new(logger).do_something }.should raise_error 19 | end 20 | 21 | it 'should do the proper logging when the load fails' do 22 | logger = mock 23 | logger.should_receive(:debug).exactly(1).times 24 | logger.should_receive(:error).once 25 | Document.load_fail = true 26 | lambda { SomeApplication.new(logger).do_something }.should raise_error 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /19/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /19/doc_block_listeners.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | 5 | # Most of the class omitted... 6 | 7 | def on_save( &block ) 8 | @save_listener = block 9 | end 10 | 11 | def on_load( &block ) 12 | @load_listener = block 13 | end 14 | 15 | def load( path ) 16 | @content = File.read( path ) 17 | @load_listener.call( self, path ) if @load_listener 18 | end 19 | 20 | def save( path ) 21 | File.open( path, 'w' ) { |f| f.print( @contents ) } 22 | @save_listener.call( self, path ) if @save_listener 23 | end 24 | end ##main) 25 | -------------------------------------------------------------------------------- /19/ex_1_explicit_blocks_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | def run_that_block( &that_block ) ##(run_that_block 4 | puts "About to run the block" 5 | that_block.call 6 | puts "Done running the block" 7 | end ##run_that_block) 8 | 9 | def run_block_with_check( &that_block ) 10 | that_block.call if that_block ##+check_block 11 | end 12 | 13 | describe 'explicit blocks' do 14 | it 'should call the block' do 15 | out = output_of { run_that_block {puts "hello"} } 16 | out.should match( /About.*hello.*Done/m ) 17 | end 18 | 19 | it 'should check that a block is supplied' do 20 | run_block_with_check 21 | out = output_of { run_block_with_check { puts 'hello' } } 22 | out.should == "hello\n" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /19/ex_4_block_load_save_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../code/doc3' 3 | require '../utils/rspec_utils' 4 | 5 | require 'doc_block_listeners' 6 | 7 | describe Document do 8 | it 'should comment on what is going on' do 9 | my_doc = Document.new( 'Block Based Example', 'russ', '' ) ##(main 10 | 11 | my_doc.on_load do |doc| 12 | puts "Hey, I've been loaded!" 13 | end 14 | 15 | my_doc.on_save do |doc| 16 | puts "Hey, I've been saved!" 17 | end ##main) 18 | 19 | save_out = output_of { my_doc.save("example.txt") } 20 | load_out = output_of { my_doc.load("example.txt") } 21 | 22 | puts save_out 23 | puts load_out 24 | save_out.should match(/Hey.*saved/m) 25 | load_out.should match(/Hey.*loaded/m) 26 | end 27 | end 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /19/ex_5_archival_doc_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | 4 | class ArchivalDocument ##(main 5 | attr_reader :title, :author 6 | 7 | def initialize(title, author, path) 8 | @title = title 9 | @author = author 10 | @path = path 11 | end 12 | 13 | def content 14 | @content ||= File.read( @path ) 15 | end 16 | end ##main) 17 | 18 | 19 | 20 | describe ArchivalDocument do 21 | before :each do 22 | File.open( 'archive.txt', 'w' ) {|f| f.puts("hello out there")} 23 | end 24 | 25 | it 'know how to load from a file' do 26 | doc = ArchivalDocument.new( 'Archive doc', 'russ', 'archive.txt' ) 27 | doc.instance_variable_get(:@content).should == nil 28 | doc.content.should == "hello out there\n" 29 | doc.instance_variable_get(:@content).should_not == nil 30 | File.delete('archive.txt') 31 | doc.content.should == "hello out there\n" 32 | end 33 | end 34 | 35 | -------------------------------------------------------------------------------- /19/ex_8_big_array_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_block_listeners' 2 | 3 | def some_method(doc) ##(main 4 | big_array = Array.new(10000000) 5 | 6 | # Do something with big_array... 7 | 8 | doc.on_load do |d| 9 | puts "Hey, I've been loaded!" 10 | end 11 | end ##main) 12 | 13 | describe 'some_method' do 14 | it 'should just work' do 15 | doc = Document.new( 'Block Based Example', 'russ', '' ) 16 | some_method(doc) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /19/ex_8a_array_no_block_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_block_listeners' 2 | 3 | def some_method(doc) ##(main 4 | big_array = Array.new(10000000) 5 | 6 | # Do something with big_array... 7 | 8 | end ##main) 9 | 10 | describe 'some_method' do 11 | it 'should just work' do 12 | doc = Document.new( 'Block Based Example', 'russ', '' ) 13 | some_method(doc) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /19/ex_8b_big_array_fixed_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_block_listeners' 2 | 3 | def some_method(doc) ##(main 4 | big_array = Array.new(10000000) 5 | 6 | # Do something with big_array... 7 | 8 | # And now get rid of it! 9 | 10 | big_array = nil 11 | 12 | doc.on_load do |d| 13 | puts "Hey, I've been loaded!" 14 | end 15 | end ##main) 16 | 17 | describe 'some_method' do 18 | it 'should just work' do 19 | doc = Document.new( 'Block Based Example', 'russ', '' ) 20 | some_method(doc) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /19/ex_9_spec.rb: -------------------------------------------------------------------------------- 1 | require 'doc_block_listeners' 2 | 3 | describe Document do 4 | it "should know how many words it contains" do ##(main 5 | doc = Document.new('example', 'russ', 'hello world') 6 | doc.word_count.should == 2 7 | end ##main) 8 | end 9 | -------------------------------------------------------------------------------- /19/example.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russolsen/eloquent_ruby_code/a7e2a638ef9920a6f71d53529ac7801b6b594b93/19/example.txt -------------------------------------------------------------------------------- /19/saveload.txt: -------------------------------------------------------------------------------- 1 | Hey I've been loaded! 2 | Hey, I've been saved! 3 | -------------------------------------------------------------------------------- /20/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /20/at_exit_demo.rb: -------------------------------------------------------------------------------- 1 | at_exit do ##(nice 2 | puts "Have a nice day." 3 | end ##nice) 4 | 5 | 6 | at_exit do ##(bye 7 | puts "Goodbye" 8 | end ##bye) 9 | -------------------------------------------------------------------------------- /20/autoloader.rb: -------------------------------------------------------------------------------- 1 | 2 | class Object 3 | def self.const_missing( name ) 4 | file_name = "#{name.to_s.downcase}" 5 | require file_name 6 | raise "Undefined constant: #{name}" unless const_defined?(name) 7 | const_get(name) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /20/autoloader_spec.rb: -------------------------------------------------------------------------------- 1 | ## 2 | require 'autoloader' 3 | 4 | describe 'autoloading example' do 5 | 6 | it "should load classes automatically by filename" do 7 | ##start 8 | today = Date.new 9 | fruit = Set.new( [ 'apple', 'orange', 'blueberry' ] ) 10 | ##end 11 | end 12 | 13 | end 14 | -------------------------------------------------------------------------------- /20/bye.txt: -------------------------------------------------------------------------------- 1 | Goodbye 2 | Have a nice day. 3 | -------------------------------------------------------------------------------- /20/document_reader.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | 3 | class DocumentReader ##(doc 4 | 5 | class << self 6 | attr_reader :reader_classes 7 | end 8 | 9 | @reader_classes = [] 10 | 11 | def self.read(path) 12 | reader = reader_for(path) 13 | return nil unless reader 14 | reader.read(path) 15 | end 16 | 17 | def self.reader_for(path) 18 | reader_class = DocumentReader.reader_classes.find do |klass| 19 | klass.can_read?(path) 20 | end 21 | return reader_class.new(path) if reader_class 22 | nil 23 | end 24 | 25 | # One critical bit omitted, but stay tuned... 26 | end ##doc) 27 | 28 | class DocumentReader 29 | 30 | # ... the vital missing piece ##(vital 31 | 32 | def self.inherited(subclass) 33 | DocumentReader.reader_classes << subclass 34 | end ##vital) 35 | end 36 | -------------------------------------------------------------------------------- /20/ex_1_inherit_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'inherit example' do 4 | it 'should produce the right output' do 5 | out = output_of { 6 | load 'inherited_demo.rb' 7 | } 8 | 9 | out.should match(/.*ChildClassOne.*subclass.*SimpleBaseClass/) 10 | 11 | File.write( 'inherit.txt', out ) 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /20/ex_2_included_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | module WritingQuality ##(wq 4 | def self.included(klass) 5 | puts "Hey, I've been included in #{klass}" 6 | end 7 | 8 | def number_of_cliches 9 | # Body of method omitted... 10 | end 11 | end ##wq) 12 | 13 | class Dummy 14 | public_class_method :include 15 | end 16 | 17 | describe WritingQuality do 18 | it 'should squak when you include it' do 19 | out = output_of { Dummy.include(WritingQuality) } 20 | out.should match( /Hey/ ) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /20/ex_3_extend_include_spec.rb: -------------------------------------------------------------------------------- 1 | module UsefulInstanceMethods ##(main 2 | def an_instance_method 3 | end 4 | end 5 | 6 | module UsefulClassMethods 7 | def a_class_method 8 | end 9 | end 10 | 11 | class Host 12 | include UsefulInstanceMethods 13 | extend UsefulClassMethods 14 | end ##main) 15 | 16 | describe Host do 17 | it 'should include UsefulInstanceMethods' do 18 | h = Host.new 19 | h.an_instance_method 20 | end 21 | 22 | it 'should have the class method' do 23 | Host.a_class_method 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /20/ex_4_include_with_auto_extend_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | module UsefulMethods ##(main 4 | module ClassMethods 5 | def a_class_method 6 | end 7 | end 8 | 9 | def self.included( host_class ) 10 | host_class.extend( ClassMethods ) 11 | end 12 | 13 | def an_instance_method 14 | end 15 | 16 | # Rest of the module deleted... 17 | end 18 | 19 | class Host 20 | include UsefulMethods 21 | end ##main) 22 | 23 | describe Host do 24 | it 'should include InstanceMethods' do 25 | h = Host.new 26 | h.an_instance_method 27 | end 28 | 29 | it 'should have the class method' do 30 | Host.a_class_method 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /20/ex_4a_exit_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | 4 | describe 'at_exit demo' do 5 | it 'should print the right stuff' do 6 | out = `ruby at_exit_demo.rb` 7 | out.should match( /Goodbye.*Have a/m) 8 | File.write( 'bye.txt', out ) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /20/ex_5_trace_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | 4 | describe 'trace demo' do 5 | it 'should print the right stuff' do 6 | out = `ruby trace_func_demo.rb` 7 | out.size.should > 5000 8 | lines = out.split("\n") 9 | lines = lines[0..7] 10 | File.write( 'trace.txt', lines.join("\n" ) ) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /20/ex_6_when_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'document_reader' 3 | 4 | class DocumentReader ##(main 5 | # Stuff omitted... 6 | end 7 | 8 | 9 | class PlainTextReader < DocumentReader 10 | # Stuff omitted... 11 | end 12 | 13 | # inherited method for PlainTextReader goes off about now... 14 | 15 | class YAMLReader < DocumentReader 16 | # Stuff omitted... 17 | end 18 | 19 | # inherited method for YAMLReader goes off about now... ##main) 20 | 21 | describe 'inherit description' do 22 | it 'should just be syntax. correct' do 23 | PlainTextReader.superclass.should == DocumentReader 24 | YAMLReader.superclass.should == DocumentReader 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /20/ex_7_unexpected_inherit_spec.rb: -------------------------------------------------------------------------------- 1 | require 'readers' 2 | 3 | class AsianDocumentReader < DocumentReader ##(classes 4 | # Lots of code for dealing with Asian languages... 5 | end 6 | 7 | class JapaneseDocumentReader < AsianDocumentReader 8 | # Lots of stuff omitted... 9 | end 10 | 11 | class ChineseDocumentReader < AsianDocumentReader 12 | # Lots of stuff omitted... 13 | end ##classes) 14 | 15 | class AsianDocumentReader < DocumentReader ##(fix 16 | def self.can_read?(path) 17 | false 18 | end 19 | 20 | # Lots of code for dealing with Asian languages... 21 | end ##fix) 22 | 23 | 24 | describe DocumentReader do 25 | it 'should have an entry for asian documents' do 26 | readers = DocumentReader.instance_variable_get( :@reader_classes ) 27 | readers.size.should == 6 28 | readers.should include(AsianDocumentReader) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /20/inherit.txt: -------------------------------------------------------------------------------- 1 | Hey ChildClassOne is now a subclass of SimpleBaseClass! 2 | -------------------------------------------------------------------------------- /20/inherited_demo.rb: -------------------------------------------------------------------------------- 1 | class SimpleBaseClass ##(base 2 | def self.inherited( new_subclass ) 3 | puts "Hey #{new_subclass} is now a subclass of #{self}!" 4 | end 5 | end ##base) 6 | 7 | 8 | class ChildClassOne < SimpleBaseClass ##(child 9 | end ##child) 10 | -------------------------------------------------------------------------------- /20/plain.txt: -------------------------------------------------------------------------------- 1 | Garp 2 | Irving 3 | Odd odd odd 4 | -------------------------------------------------------------------------------- /20/plaintext_reader.rb: -------------------------------------------------------------------------------- 1 | class PlainTextReader < DocumentReader ##(plain 2 | def self.can_read?(path) 3 | /.*\.txt/ =~ path 4 | end 5 | 6 | def initialize(path) 7 | @path = path 8 | end 9 | 10 | def read(path) 11 | File.open(path) do |f| 12 | title = f.readline.chomp 13 | author = f.readline.chomp 14 | content = f.read.chomp 15 | Document.new( title, author, content ) 16 | end 17 | end 18 | end ##plain) 19 | -------------------------------------------------------------------------------- /20/readers.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | require 'document_reader' ##(main 4 | 5 | require 'plaintext_reader' # inherited fires for PlainTextReader 6 | require 'xml_reader' # inherited fires for XMLReader 7 | require 'yaml_reader' # inherited fires for YAMLReader ##main) 8 | -------------------------------------------------------------------------------- /20/trace.txt: -------------------------------------------------------------------------------- 1 | c-return in trace_func_demo.rb/5 set_trace_func Kernel 2 | line in trace_func_demo.rb/10 3 | c-call in trace_func_demo.rb/10 require Kernel 4 | c-return in trace_func_demo.rb/10 require Kernel 5 | line in trace_func_demo.rb/11 6 | c-call in trace_func_demo.rb/11 require Kernel 7 | c-call in trace_func_demo.rb/11 set_encoding IO 8 | c-return in trace_func_demo.rb/11 set_encoding IO -------------------------------------------------------------------------------- /20/trace_func_demo.rb: -------------------------------------------------------------------------------- 1 | proc_object = proc do |event, file, line, id, binding, klass| 2 | puts "#{event} in #{file}/#{line} #{id} #{klass}" 3 | end 4 | 5 | set_trace_func(proc_object) 6 | 7 | # Since date is apparently already loaded, we will also 8 | # load treetop to generate some serious tracing. 9 | # 10 | require 'date' 11 | require 'treetop' 12 | -------------------------------------------------------------------------------- /20/xml_reader.rb: -------------------------------------------------------------------------------- 1 | class XMLReader < DocumentReader 2 | def self.can_read?(path) 3 | /.*\.xml/ =~ path 4 | end 5 | 6 | def initialize(path) 7 | @path = path 8 | end 9 | 10 | def read(path) 11 | # Lots of complicated XML stuff omitted 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /20/yaml_reader.rb: -------------------------------------------------------------------------------- 1 | class YAMLReader < DocumentReader 2 | def self.can_read?(path) 3 | /.*\.yaml/ =~ path 4 | end 5 | 6 | def initialize(path) 7 | @path = path 8 | end 9 | 10 | def read(path) 11 | # Lots of simple YAML stuff omitted 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /21/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | 3 | CLEAN.include(%w{guess.txt document.error repeat.txt}) 4 | -------------------------------------------------------------------------------- /21/ex_1_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | describe 'calling the wrong method' do 4 | 5 | it 'should just blow up' do 6 | lambda { 7 | # Error: the method is content, not text! ##(main 8 | 9 | doc = Document.new('Titanic', 'Cameron', 'Sail, crash, sink') 10 | puts "The text is #{doc.text}" ##main) 11 | }.should raise_error 12 | 13 | end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /21/ex_2_repeat_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | class RepeatBackToMe ##(main 4 | def method_missing( method_name, *args ) 5 | puts "Hey, you just called the #{method_name} method" 6 | puts "With these arguments: #{args.join(' ')}" 7 | puts "But there ain't no such method" 8 | end 9 | end ##main) 10 | 11 | 12 | describe RepeatBackToMe do 13 | 14 | it 'should output the method' do 15 | out = output_of { 16 | repeat = RepeatBackToMe.new ##(example 17 | repeat.hello( 1, 2, 3 ) 18 | repeat.good_bye( "for", "now" ) ##example) 19 | } 20 | 21 | out.should match( /^Hey.*hello method.*1 2 3.*good_by.*now$/m ) 22 | File.write( 'repeat.txt', out ) 23 | end 24 | 25 | 26 | end 27 | -------------------------------------------------------------------------------- /21/ex_3_doc_missing_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc3' 3 | 4 | class Document ##(main 5 | # Most of the class omitted... 6 | 7 | def method_missing( method_name, *args ) 8 | msg = %Q{ 9 | You tried to call the method #{method_name} 10 | on an instance of Document. There is no such method. 11 | } 12 | raise msg 13 | end 14 | end ##main) 15 | 16 | describe Document do 17 | 18 | it 'should complain correctly' do 19 | doc = Document.new('Titanic', 'Cameron', 'Sail, crash, sink') 20 | begin 21 | puts "The text is #{doc.text}" 22 | rescue 23 | $!.message.should match( /.*You tried.*method text.*no such.*/m ) 24 | end 25 | end 26 | 27 | 28 | end 29 | -------------------------------------------------------------------------------- /21/ex_4_doc_to_file_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc3' 3 | 4 | class Document ##(main 5 | # Most of the class omitted... 6 | 7 | def method_missing( method_name, *args ) 8 | File.open( 'document.error', 'a' ) do |f| 9 | f.puts( "Bad method called: #{method_name}" ) 10 | f.puts( "with #{args.size} arguments" ) 11 | end 12 | super 13 | end 14 | end ##main) 15 | 16 | describe Document do 17 | 18 | it 'should write the error to a file' do 19 | File.delete('document.error') if File.exist?('document.error') 20 | 21 | doc = Document.new('Titanic', 'Cameron', 'Sail, crash, sink') 22 | 23 | lambda { 24 | puts "The text is #{doc.text}" 25 | }.should raise_error 26 | 27 | out = File.read( 'document.error' ) 28 | out.should match( /.*Bad method called.*text*/m ) 29 | end 30 | 31 | 32 | end 33 | -------------------------------------------------------------------------------- /21/ex_6_autoload_const_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc3' 3 | 4 | class Document ##(main 5 | # Most of the class omitted... 6 | 7 | def self.const_missing( const_name ) 8 | msg = %Q{ 9 | You tried to reference the constant #{const_name} 10 | There is no such constant in the Document class. 11 | } 12 | raise msg 13 | end 14 | end ##main) 15 | 16 | describe Document do 17 | 18 | it 'should complain correctly' do 19 | doc = Document.new('Titanic', 'Cameron', 'Sail, crash, sink') 20 | begin 21 | Document::FooBar 22 | rescue 23 | $!.message.should match( /.*You tried.*constant FooBar.*no such.*/m ) 24 | end 25 | end 26 | 27 | 28 | end 29 | -------------------------------------------------------------------------------- /21/ex_6_const_missing_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc3' 3 | 4 | class Document ##(main 5 | # Most of the class omitted... 6 | 7 | def self.const_missing( const_name ) 8 | msg = %Q{ 9 | You tried to reference the constant #{const_name} 10 | There is no such constant in the Document class. 11 | } 12 | raise msg 13 | end 14 | end ##main) 15 | 16 | describe Document do 17 | 18 | it 'should complain correctly' do 19 | doc = Document.new('Titanic', 'Cameron', 'Sail, crash, sink') 20 | begin 21 | Document::FooBar 22 | rescue 23 | $!.message.should match( /.*You tried.*constant FooBar.*no such.*/m ) 24 | end 25 | end 26 | 27 | 28 | end 29 | -------------------------------------------------------------------------------- /21/ex_7_autoload_const_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | class AutoLoad 4 | def self.const_missing( name ) ##(main 5 | file_name = "#{name.to_s.downcase}" 6 | require file_name 7 | raise "Undefined: #{name}" unless const_defined?(name) 8 | const_get(name) 9 | end ##main) 10 | end 11 | 12 | describe AutoLoad do 13 | 14 | it 'should autoload files' do 15 | clazz = AutoLoad::Example 16 | clazz.class.should == Class 17 | end 18 | 19 | it 'should blow up on undefined files' do 20 | lambda { clazz = AutoLoad::FooBar }.should raise_error 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /21/example.rb: -------------------------------------------------------------------------------- 1 | # Example Ruby class for autoloading 2 | 3 | 4 | class Example 5 | end 6 | -------------------------------------------------------------------------------- /22/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | 3 | CLEAN.include(%w{hare.txt to_s.txt}) 4 | 5 | -------------------------------------------------------------------------------- /22/ssdoc_mm.rb: -------------------------------------------------------------------------------- 1 | class SuperSecretDocument ##(main 2 | def initialize(original_document, time_limit_seconds) 3 | @original_document = original_document 4 | @time_limit_seconds = time_limit_seconds 5 | @create_time = Time.now 6 | end 7 | 8 | def time_expired? 9 | Time.now - @create_time >= @time_limit_seconds 10 | end 11 | 12 | def check_for_expiration 13 | raise 'Document no longer available' if time_expired? 14 | end 15 | 16 | def method_missing(name, *args) 17 | check_for_expiration 18 | @original_document.send(name, *args) ##+send 19 | end 20 | end ##main) 21 | -------------------------------------------------------------------------------- /23/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | 3 | CLEAN.include(%w{conflict.txt}) 4 | 5 | -------------------------------------------------------------------------------- /23/ex_formletter2_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc3' 3 | 4 | 5 | class FormLetter < Document ##(main 6 | 7 | def replace_word( old_word, new_word ) 8 | @content.gsub!( old_word, "#{new_word}" ) 9 | end 10 | 11 | def replace_firstname( new_first_name ) 12 | replace_word( 'FIRSTNAME', new_first_name ) 13 | end 14 | 15 | def replace_lastname( new_last_name ) 16 | replace_word( 'LASTNAME', new_last_name ) 17 | end 18 | end ##main) 19 | 20 | describe 'FormLetter with conv. methods' do 21 | it "should know how to replace fn and ln" do 22 | fl = FormLetter.new( "form", "russ", "FIRSTNAME LASTNAME" ) 23 | fl.replace_firstname( 'Fred' ) 24 | fl.replace_lastname( 'Flip' ) 25 | fl.content.should == 'Fred Flip' 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /23/ostruct_spec.rb: -------------------------------------------------------------------------------- 1 | require 'ostruct' 2 | 3 | describe OpenStruct do 4 | it 'should just work' do 5 | author = OpenStruct.new 6 | author.first_name = 'Stephen' 7 | author.last_name = 'Hawking' 8 | puts author.first_name 9 | puts author.last_name 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /24/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /24/document.rb: -------------------------------------------------------------------------------- 1 | # Dummy document file, used just to make the requires in 2 | # examples look right. 3 | -------------------------------------------------------------------------------- /24/ex_1_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4' 2 | require '../utils/rspec_utils' 3 | 4 | describe 'initial examples in chapter' do 5 | it 'should demo simple vars correctly' do 6 | name = 'Issac' ##+name1 7 | name = 'Asimov' ##+name2 8 | 9 | name.should == 'Asimov' 10 | end 11 | 12 | it 'should demo the average_word_length method correctly' do 13 | cover_letter = Document.new( 'Letter', 'Russ', "Here's my resume" ) ##+cover 14 | 15 | avg = ( 16 | cover_letter.average_word_length ##+avg_word_len 17 | ) 18 | (avg - 4.666667).abs.should < 0.001 19 | end 20 | 21 | it 'should demo bad things with empty docs' do 22 | out = output_of { 23 | empty_doc = Document.new( 'Empty!', 'Russ', '' ) ##(empty 24 | puts empty_doc.average_word_length ##empty) 25 | } 26 | out.should == "NaN\n" 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /24/ex_alias_method_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4' 2 | 3 | class Document ##(main 4 | # Stuff omitted... 5 | 6 | def word_count 7 | words.size 8 | end 9 | 10 | alias_method :number_of_words, :word_count 11 | alias_method :size_in_words, :word_count 12 | 13 | # Stuff omitted... 14 | end ##main) 15 | 16 | describe 'aliases' do 17 | 18 | it 'should provide a copy of the method' do 19 | doc = Document.new( 'example', 'russ', 'one two three' ) 20 | doc.word_count.should == 3 21 | doc.word_count.should == doc.number_of_words 22 | doc.word_count.should == doc.size_in_words 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /24/ex_alias_patch_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4' 2 | 3 | class String ##(string 4 | alias_method :old_addition, :+ 5 | 6 | def +( other ) 7 | if other.kind_of? Document 8 | new_content = self + other.content 9 | return Document.new(other.title, other.author, new_content) 10 | end 11 | old_addition(other) 12 | end 13 | end ##string) 14 | 15 | describe String do 16 | it 'should know how to add itself to a Document' do 17 | d1 = Document.new( 'example', 'russ', 'out there' ) 18 | d2 = 'hello ' + d1 19 | d2.author.should == 'russ' 20 | d2.title.should == 'example' 21 | d2.content.should == 'hello out there' 22 | end 23 | 24 | it "should still be able to add" do 25 | ('aaa' + 'bbb').should == 'aaabbb' 26 | ('' + 'bbb').should == 'bbb' 27 | ('aaa' + '').should == 'aaa' 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /24/ex_fix_bug_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4' 2 | 3 | require 'document' # Pull in original, broken class ##(main 4 | 5 | class Document 6 | def average_word_length 7 | return 0.0 if word_count == 0 8 | total = words.inject(0.0){ |result, word| word.size + result} 9 | total / word_count 10 | end 11 | end ##main) 12 | 13 | 14 | describe 'monkey patched document class' do 15 | 16 | it 'should return 0.0 for an empty document' do 17 | d = Document.new( 'empty', 'russ', '' ) 18 | d.average_word_length.should == 0.0 19 | d.content = 'hello' 20 | d.average_word_length.should == 5.0 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /24/ex_no_wordcount_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require '../code/doc4.rb' 3 | 4 | class Document ##(main 5 | remove_method :word_count 6 | end ##main) 7 | 8 | 9 | describe 'document with private word_count' do 10 | it 'should have a private wordcount method' do 11 | doc = Document.new( 'example', 'russ', 'hello world' ) 12 | lambda { doc.word_count }.should raise_error 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /24/ex_private_wordcount_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4.rb' 2 | 3 | class Document ##(main 4 | private :word_count 5 | end ##main) 6 | 7 | describe 'document with private word_count' do 8 | it 'should have a private wordcount method' do 9 | doc = Document.new( 'example', 'russ', 'hello world' ) 10 | lambda { doc.word_count }.should raise_error 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /24/ex_public_wordcount_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4.rb' 2 | 3 | class Document 4 | private :word_count 5 | end 6 | 7 | class Document ##(main 8 | public :word_count 9 | end ##main) 10 | 11 | describe 'document with private word_count' do 12 | it 'should have a private wordcount method' do 13 | doc = Document.new( 'example', 'russ', 'hello world' ) 14 | doc.word_count 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /24/ex_string_patch_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc4' 2 | 3 | class String ##(string 4 | def +( other ) 5 | if other.kind_of? Document 6 | new_content = self + other.content 7 | return Document.new(other.title, other.author, new_content) 8 | end 9 | result = self.dup 10 | result << other.to_str 11 | result 12 | end 13 | end ##string) 14 | 15 | describe String do 16 | it 'should know how to add itself to a Document' do 17 | d1 = Document.new( 'example', 'russ', 'out there' ) 18 | d2 = 'hello ' + d1 19 | d2.author.should == 'russ' 20 | d2.title.should == 'example' 21 | d2.content.should == 'hello out there' 22 | end 23 | 24 | it "should still be able to add" do 25 | ('aaa' + 'bbb').should == 'aaabbb' 26 | ('' + 'bbb').should == 'bbb' 27 | ('aaa' + '').should == 'aaa' 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /25/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | 3 | CLEAN.include(%w{hello.txt junk.txt lessempty.txt second.txt self.txt}) 4 | CLEAN.include(%w{foo.rb}) 5 | 6 | -------------------------------------------------------------------------------- /25/broken_encrypting_document.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | ENCRYPTION_ENABLED = true 4 | 5 | class Document 6 | 7 | # Most of the class left behind... 8 | 9 | def self.enable_encryption( enabled ) ##(main 10 | if enabled 11 | def encrypt_string( string ) 12 | string.tr( 'a-zA-Z', 'm-za-lM-ZA-L') 13 | end 14 | else 15 | def incrypt_string( string ) 16 | string 17 | end 18 | end 19 | end ##main) 20 | enable_encryption( ENCRYPTION_ENABLED ) 21 | end 22 | -------------------------------------------------------------------------------- /25/encrypting_document.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | ENCRYPTION_ENABLED = true ##(main 4 | 5 | class Document 6 | 7 | # Most of the class left behind... 8 | 9 | def self.enable_encryption( enabled ) 10 | if enabled 11 | def encrypt_string( string ) 12 | string.tr( 'a-zA-Z', 'm-za-lM-ZA-L') 13 | end 14 | else 15 | def encrypt_string( string ) 16 | string 17 | end 18 | end 19 | end 20 | 21 | enable_encryption( ENCRYPTION_ENABLED ) 22 | end ##main) 23 | -------------------------------------------------------------------------------- /25/ex_1_mostly_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'class definition' do 4 | it 'should execute code inside of class statement' do 5 | out = output_of { 6 | class MostlyEmpty ##(hello_inside 7 | puts "hello from inside the class" 8 | end ##hello_inside) 9 | } 10 | out.should match(/hello from/) 11 | File.write( 'hello.txt', out ) 12 | end 13 | 14 | it 'should make self the class inside of the def' do 15 | out = output_of { 16 | class MostlyEmpty ##(self_inside 17 | puts "The value of self is #{self}" 18 | end ##self_inside) 19 | } 20 | out.should match(/The value.*MostlyEmpty/) 21 | File.write( 'self.txt', out ) 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /25/ex_2_one_step_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require 'pp' 3 | 4 | describe 'class definition' do 5 | it 'should define methods one at a time' do 6 | out = output_of { 7 | class TheSameMethodTwice ##(main 8 | 9 | def do_something 10 | puts "first version" 11 | end 12 | 13 | # In between method definitions 14 | 15 | def do_something 16 | puts "second version" 17 | end 18 | end 19 | 20 | twice = TheSameMethodTwice.new 21 | twice.do_something ##main) 22 | } 23 | out.should match(/second version/) 24 | File.write( 'second.txt', out ) 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /25/ex_3_sep_classes_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require 'pp' 3 | 4 | describe 'class definition' do 5 | it 'should define methods one at a time' do 6 | out = output_of { 7 | class TheSameMethodTwice ##(main 8 | def do_something 9 | puts "first version" 10 | end 11 | end 12 | 13 | class TheSameMethodTwice 14 | def do_something 15 | puts "second version" 16 | end 17 | end ##main) 18 | 19 | smt = TheSameMethodTwice.new 20 | smt.do_something 21 | } 22 | out.should match(/second version/) 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /25/ex_3_twice_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | require 'pp' 3 | 4 | describe 'class definition' do 5 | it 'should define methods one at a time' do 6 | out = output_of { 7 | class LessEmpty ##(main 8 | pp instance_methods(false) 9 | 10 | def do_something 11 | puts "I'm doing something!" 12 | end 13 | 14 | pp instance_methods(false) 15 | end ##main) 16 | } 17 | out.should match(/\[\]\n\[:do_something\]/) 18 | File.write( 'lessempty.txt', out ) 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /25/ex_5_toggle_encryption_spec.rb: -------------------------------------------------------------------------------- 1 | require 'encrypting_document' 2 | 3 | describe Document do ##(main 4 | before :each do 5 | @doc = Document.new( "test", "tester", "this is a test" ) 6 | end 7 | 8 | it "should encrypt if encryption is enabled" do 9 | Document.enable_encryption( true ) 10 | @doc.encrypt_string( 'abc' ).should_not == 'abc' 11 | end 12 | 13 | it "should not encrypt if encryption is disabled" do 14 | Document.enable_encryption( false ) ##+enable 15 | @doc.encrypt_string( 'abc' ).should == 'abc' 16 | end 17 | end ##main) 18 | -------------------------------------------------------------------------------- /25/ex_6_char_at_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | # Ruby 1.9 version 5 | 6 | def char_at( index ) 7 | @content[ index ] 8 | end 9 | end ##main) 10 | 11 | describe Document do 12 | it 'should have a working char_at method' do 13 | d = Document.new( '', '', 'abcde' ) 14 | d.char_at(0).should == 'a' 15 | d.char_at(1).should == 'b' 16 | d.char_at(2).should == 'c' 17 | d.char_at(3).should == 'd' 18 | d.char_at(4).should == 'e' 19 | end 20 | end 21 | 22 | 23 | -------------------------------------------------------------------------------- /25/ex_7_char_at_switch_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | # Lots of stuff omitted... 5 | 6 | if RUBY_VERSION >= '1.9' 7 | def char_at( index ) 8 | @content[ index ] 9 | end 10 | else 11 | def char_at( index ) 12 | @content[ index ].chr 13 | end 14 | end 15 | end ##main) 16 | 17 | describe Document do 18 | it 'should have a working char_at method' do 19 | d = Document.new( '', '', 'abcde' ) 20 | d.char_at(0).should == 'a' 21 | d.char_at(1).should == 'b' 22 | d.char_at(2).should == 'c' 23 | d.char_at(3).should == 'd' 24 | d.char_at(4).should == 'e' 25 | end 26 | end 27 | 28 | 29 | -------------------------------------------------------------------------------- /25/ex_8_reload_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | require 'fileutils' 4 | 5 | describe Document do 6 | it 'should have a reload method' do 7 | FileUtils.cp 'reloadable_document.rb', 'foo.rb' 8 | load 'foo.rb' 9 | d = Document.new( '', '', '' ) 10 | d.doit.should == 111 11 | File.write( 'foo.rb', File.read('foo.rb').sub('111','222') ) 12 | Document.reload 13 | d.doit.should == 222 14 | end 15 | end 16 | 17 | 18 | -------------------------------------------------------------------------------- /25/ex_9_better_reloadable_spec.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | require 'fileutils' 4 | require 'pp' 5 | 6 | describe Document do 7 | it 'should have a reload method' do 8 | FileUtils.cp 'reloadable_document2.rb', 'foo.rb' 9 | load 'foo.rb' 10 | d = Document.new( '', '', '' ) 11 | d.doit.should == 111 12 | 13 | code = File.read('foo.rb') 14 | code.sub!('111','222') 15 | code.sub!( 'doit', 'zzz' ) 16 | 17 | File.write( 'foo.rb', code ) 18 | Document.reload 19 | d.zzz.should == 222 20 | Document.instance_methods.should_not include(:doit) 21 | end 22 | end 23 | 24 | 25 | -------------------------------------------------------------------------------- /25/reloadable_document.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | def self.reload 5 | load( __FILE__ ) 6 | end 7 | 8 | # Rest of the class omitted... 9 | end ##main) 10 | 11 | class Document 12 | def doit 13 | 111 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /25/reloadable_document2.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | class Document ##(main 4 | def self.reload 5 | remove_instance_methods 6 | load( __FILE__ ) 7 | end 8 | 9 | def self.remove_instance_methods 10 | instance_methods(false).each do |method| 11 | remove_method(method) 12 | end 13 | end 14 | 15 | # Rest of the class omitted... 16 | end ##main) 17 | 18 | class Document 19 | def doit 20 | 111 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /25/trouble_document.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | 3 | ENCRYPTION_ENABLED = true ##(main 4 | 5 | # Broken!! 6 | 7 | class Document 8 | 9 | # Most of the class left behind... 10 | 11 | def self.enable_encryption( enabled ) 12 | if enabled 13 | def encrypt_string( string ) 14 | string.tr( 'a-zA-Z', 'm-za-lM-ZA-L') 15 | end 16 | else 17 | def encrypt_string( string ) 18 | string 19 | end 20 | end 21 | end 22 | end ##main) 23 | -------------------------------------------------------------------------------- /26/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /26/disclaimer.txt: -------------------------------------------------------------------------------- 1 | This document is a deep, dark secret 2 | -------------------------------------------------------------------------------- /26/ex_1_struc_doc_spec.rb: -------------------------------------------------------------------------------- 1 | require 'structured_document' 2 | require 'pp' 3 | 4 | describe StructuredDocument do 5 | it 'should actually work' do 6 | russ_cv = StructuredDocument.new( 'Resume', 'RO' ) do |cv| ##(russ_cv 7 | cv << Paragraph.new( :nimbus, 14, :bold, 'Russ Olsen' ) 8 | cv << Paragraph.new( :nimbus, 12, :italic, '222 Rocky Way') 9 | cv << Paragraph.new( :nimbus, 12, :none, 'russ@russolsen.com') 10 | # .. and so on 11 | end ##russ_cv) 12 | 13 | russ_cv.paragraphs.first.text.should == 'Russ Olsen' 14 | russ_cv.paragraphs.first.font_name.should == :nimbus 15 | russ_cv.paragraphs.first.font_size.should == 14 16 | russ_cv.paragraphs.first.font_emphasis.should == :bold 17 | 18 | russ_cv.paragraphs[1].text.should match(/222.*/) 19 | russ_cv.paragraphs.last.text.should match(/@russolsen.com/) 20 | russ_cv.content.should match(/Russ.*Rocky.*olsen.com/m) 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /26/ex_4_meta_ins_spec.rb: -------------------------------------------------------------------------------- 1 | require 'structured_document' 2 | require 'structured_doc_eval' 3 | require 'pp' 4 | 5 | 6 | class Instructions < StructuredDocument ##(main 7 | paragraph_type( :introduction, 8 | :font_name => :arial, 9 | :font_size => 18, 10 | :font_emphasis => :italic ) 11 | 12 | # And so on... 13 | end ##main) 14 | 15 | 16 | describe Instructions do 17 | it 'should have the proper methods' do 18 | Instructions.instance_methods.should include( :introduction ) 19 | end 20 | 21 | it 'should produce working instruction instances' do 22 | i = Instructions.new( 'building a house', 'russ' ) 23 | i.introduction( 'This is how you build a house' ) 24 | i.introduction( 'carefully' ) 25 | 26 | i.paragraphs.first.text.should match(/This is how/) 27 | i.paragraphs.last.font_size.should == 18 28 | i.paragraphs.last.font_emphasis.should == :italic 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /26/ex_4_question_spec.rb: -------------------------------------------------------------------------------- 1 | require 'structured_document' 2 | require 'pp' 3 | 4 | 5 | class StructuredDocument ##(main 6 | def self.paragraph_type( paragraph_name, options ) 7 | # What do we do in here? 8 | end 9 | 10 | # ... 11 | end ##main) 12 | 13 | 14 | describe StructuredDocument do 15 | it 'should have the proper methods' do 16 | StructuredDocument.public_methods.should include( :paragraph_type ) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /26/ex_5_def_method_spec.rb: -------------------------------------------------------------------------------- 1 | require 'structured_document' 2 | require 'structured_doc_def_method' 3 | require 'pp' 4 | 5 | 6 | class Instructions < StructuredDocument 7 | paragraph_type( :introduction, 8 | :font_name => :arial, 9 | :font_size => 18, 10 | :font_emphasis => :bold ) 11 | 12 | # And so on... 13 | end 14 | 15 | 16 | describe Instructions do 17 | it 'should have the proper methods' do 18 | Instructions.instance_methods.should include( :introduction ) 19 | end 20 | 21 | it 'should produce working instruction instances' do 22 | i = Instructions.new( 'building a house', 'russ' ) 23 | i.introduction( 'This is how you build a house' ) 24 | i.introduction( 'carefully' ) 25 | 26 | i.paragraphs.first.text.should match(/This is how/) 27 | i.paragraphs.last.font_size.should == 18 28 | i.paragraphs.last.font_emphasis.should == :bold 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /26/ex_8_attrs_spec.rb: -------------------------------------------------------------------------------- 1 | class Printer ##(printer 2 | attr_accessor :name 3 | end ##printer) 4 | 5 | describe Printer do 6 | it 'should have the correct accessors' do 7 | methods = Printer.instance_methods 8 | methods.should include(:name) 9 | methods.should include(:name=) 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /26/ex_8_dumb_attrs_spec.rb: -------------------------------------------------------------------------------- 1 | class Printer ##(printer 2 | def name 3 | @name 4 | end 5 | 6 | def name=(value) 7 | @name = value 8 | end 9 | end ##printer) 10 | 11 | describe Printer do 12 | it 'should have the correct accessors' do 13 | methods = Printer.instance_methods 14 | methods.should include(:name) 15 | methods.should include(:name=) 16 | end 17 | 18 | it 'should work' do 19 | p = Printer.new 20 | p.name.should == nil 21 | p.name = 'epson' 22 | p.name.should == 'epson' 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /26/ex_9_forwardable.rb: -------------------------------------------------------------------------------- 1 | require '../code/doc3' 2 | require '../utils/rspec_utils' 3 | 4 | require 'forwardable' 5 | 6 | class DocumentWrapper ##(main 7 | extend Forwardable 8 | 9 | def_delegators :@real_doc, :title, :author, :content 10 | 11 | def initialize( real_doc ) 12 | @real_doc = real_doc 13 | end 14 | end ##main) 15 | 16 | 17 | 18 | describe DocumentWrapper do 19 | it 'should work' do 20 | real_doc = wrapped_doc = nil 21 | 22 | out = output_of { 23 | real_doc = Document.new( 'Two Cities', 'Dickens', 'It was...' ) ##(ex 24 | wrapped_doc = DocumentWrapper.new( real_doc ) 25 | 26 | puts wrapped_doc.title 27 | puts wrapped_doc.author 28 | puts wrapped_doc.content ##ex) 29 | } 30 | 31 | out.should match(/Two.*Dickens.*Best/m) 32 | 33 | wrapped_doc.title.should == real_doc.title 34 | wrapped_doc.author.should == real_doc.author 35 | wrapped_doc.content.should == real_doc.content 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /26/forw.rb: -------------------------------------------------------------------------------- 1 | module Forwardable 2 | # Lots of code deleted... 3 | 4 | def def_instance_delegator(accessor, method, ali = method) 5 | str = %{ 6 | def #{ali}(*args, &block) 7 | #{accessor}.__send__(:#{method}, *args, &block) 8 | end 9 | } 10 | module_eval(str, __FILE__, line_no) 11 | end 12 | 13 | end 14 | -------------------------------------------------------------------------------- /26/my_attr.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Object 4 | def self.simple_attr_reader(name) 5 | code = "def #{name}; @#{name}; end" 6 | class_eval( code ) 7 | end 8 | end 9 | 10 | class Object 11 | def self.simple_attr_writer(name) 12 | method_name = "#{name}=" 13 | define_method( method_name ) do |value| 14 | variable_name = "@#{name}" 15 | instance_variable_set( variable_name, value ) 16 | end 17 | end 18 | end 19 | 20 | class Example 21 | simple_attr_reader :color 22 | simple_attr_writer :color 23 | 24 | def initialize( color ) 25 | @color = color 26 | end 27 | end 28 | 29 | e = Example.new( 'green' ) 30 | puts e.color 31 | e.color = 'red' 32 | puts e.color 33 | -------------------------------------------------------------------------------- /26/structured_doc_def_method.rb: -------------------------------------------------------------------------------- 1 | require 'structured_document' 2 | require 'pp' 3 | 4 | 5 | class StructuredDocument ##(main 6 | def self.paragraph_type( paragraph_name, options ) 7 | name = options[:font_name] || :arial 8 | size = options[:font_size] || 12 9 | emphasis = options[:font_emphasis] || :none 10 | 11 | define_method(paragraph_name) do |text| 12 | paragraph = Paragraph.new( name, size, emphasis, text ) 13 | self << paragraph 14 | end 15 | end 16 | 17 | # ... 18 | end ##main) 19 | -------------------------------------------------------------------------------- /26/structured_doc_eval.rb: -------------------------------------------------------------------------------- 1 | require 'structured_document' 2 | require 'pp' 3 | 4 | class StructuredDocument ##(main 5 | def self.paragraph_type( paragraph_name, options ) 6 | 7 | name = options[:font_name] || :arial 8 | size = options[:font_size] || 12 9 | emphasis = options[:font_emphasis] || :normal 10 | 11 | code = %Q{ 12 | def #{paragraph_name}(text) 13 | p = Paragraph.new(:#{name}, #{size}, :#{emphasis}, text) 14 | self << p 15 | end 16 | } 17 | class_eval( code ) 18 | end 19 | 20 | # ... 21 | end ##main) 22 | -------------------------------------------------------------------------------- /27/Rakefile: -------------------------------------------------------------------------------- 1 | require '../utils/tasks.rb' 2 | -------------------------------------------------------------------------------- /27/Rakefile.example: -------------------------------------------------------------------------------- 1 | ##(main 2 | task :default => [ :install_program , :install_data ] ##+default 3 | 4 | task :install_data => :installation_dir do 5 | cp 'fonts.dat', 'installation' 6 | end 7 | 8 | task :install_program => [ :installation_dir ] do 9 | cp 'document.rb', 'installation' 10 | end 11 | 12 | task :installation_dir do 13 | mkdir_p 'installation' 14 | end ##main) 15 | 16 | -------------------------------------------------------------------------------- /27/broken.ripper: -------------------------------------------------------------------------------- 1 | # Error: Note the missing do on the first line... 2 | 3 | on_path( '/document/author' ) |author| 4 | author.text = 'Tolkien' 5 | end 6 | 7 | after { |doc| puts doc } 8 | -------------------------------------------------------------------------------- /27/ex_1_author.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "rexml/document" 4 | 5 | File.open( 'fellowship.xml' ) do |f| 6 | doc = REXML::Document.new(f) 7 | author = REXML::XPath.first(doc, '/document/author') 8 | puts author.text 9 | end 10 | -------------------------------------------------------------------------------- /27/ex_1_fix.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "rexml/document" 4 | 5 | File.open( 'fellowship.xml' ) do |f| 6 | doc = REXML::Document.new(f) 7 | REXML::XPath.each(doc, '/document/author') do |author| 8 | author.text = 'J.R.R. Tolkien' 9 | end 10 | puts doc 11 | end 12 | 13 | -------------------------------------------------------------------------------- /27/ex_1_simple_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe "simple script examples" do 4 | 5 | it 'author example should work' do 6 | out = `ruby ex_1_author.rb` 7 | out.should == "J. R. R. Tolken\n" 8 | end 9 | 10 | 11 | it 'title example should work' do 12 | out = `ruby ex_1_title.rb` 13 | out.should == "A Long Expected Party\nA Shadow Of The Past\n" 14 | end 15 | 16 | it 'fix misspelling example should work' do 17 | out = `ruby ex_1_fix.rb` 18 | out.should match( /author>J.R.R. Tolkien/ ) 19 | end 20 | end 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /27/ex_1_title.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "rexml/document" 4 | 5 | File.open( 'fellowship.xml' ) do |f| 6 | doc = REXML::Document.new(f) 7 | REXML::XPath.each(doc, '/document/chapter/title') do |title| 8 | puts title.text 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /27/fellowship.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The Fellowship Of The Ring 5 | J. R. R. Tolken 6 | 1954 7 | 8 | 9 | A Long Expected Party 10 | When Mr. Bilbo Bagins of Bag End... 11 | 12 | 13 | 14 | A Shadow Of The Past 15 | The talk did not die down... 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /27/fix_author.ripper: -------------------------------------------------------------------------------- 1 | on_path( '/document/author' ) do |author| 2 | author.text = 'J.R.R. Tolkien' 3 | end 4 | after { |doc| puts doc } 5 | -------------------------------------------------------------------------------- /27/fix_author_comments.ripper: -------------------------------------------------------------------------------- 1 | # Correct a common mistake 2 | 3 | on_path( '/document/author' ) do |author| 4 | author.text = 'J.R.R. Tolkien' 5 | end 6 | 7 | # Print out the whole document when done 8 | 9 | after { |doc| puts doc } 10 | -------------------------------------------------------------------------------- /27/migration_example.rb: -------------------------------------------------------------------------------- 1 | class AddBooks < ActiveRecord::Migration 2 | def self.up 3 | create_table :books do |t| 4 | t.string :title 5 | t.integer :publisher_id 6 | end 7 | end 8 | 9 | def self.down 10 | drop_table :books 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /27/on_doc_author.ripper: -------------------------------------------------------------------------------- 1 | on_document_author { |author| puts author.text } 2 | -------------------------------------------------------------------------------- /27/ripper1.rb: -------------------------------------------------------------------------------- 1 | require "rexml/document" 2 | 3 | class XmlRipper 4 | def initialize(&block) 5 | @before_action = proc {} 6 | @path_actions = {} 7 | @after_action = proc {} 8 | block.call( self ) if block 9 | end 10 | 11 | def on_path( path, &block ) 12 | @path_actions[path] = block 13 | end 14 | 15 | def before( &block ) 16 | before_action = block 17 | end 18 | 19 | def after( &block ) 20 | @after_action = block 21 | end 22 | 23 | def run( xml_file_path ) 24 | File.open( xml_file_path ) do |f| 25 | document = REXML::Document.new(f) 26 | @before_action.call( document ) 27 | run_path_actions( document ) 28 | @after_action.call( document ) 29 | end 30 | end 31 | 32 | def run_path_actions( document ) 33 | @path_actions.each do |path, block| 34 | REXML::XPath.each(document, path) do |element| 35 | block.call( element ) 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /27/ripper1_fix_author.rb: -------------------------------------------------------------------------------- 1 | require 'ripper1' 2 | 3 | ripper = XmlRipper.new do |r| ##(main 4 | r.on_path( '/document/author' ) do |author| 5 | author.text = 'J.R.R. Tolkien' 6 | end 7 | r.after { |doc| puts doc } 8 | end 9 | 10 | ripper.run( 'fellowship.xml' ) ##main) 11 | -------------------------------------------------------------------------------- /27/ripper1_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe "first ripper scripts" do 4 | 5 | it 'author example should work' do 6 | out = `ruby -I . ripper1_title_author.rb` 7 | out.should == "J. R. R. Tolken\nA Long Expected Party\nA Shadow Of The Past\n" 8 | end 9 | 10 | 11 | it 'fix misspelling example should work' do 12 | out = `ruby -I . ripper1_fix_author.rb` 13 | out.should match( /author>J.R.R. Tolkien/ ) 14 | end 15 | end 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /27/ripper1_title_author.rb: -------------------------------------------------------------------------------- 1 | require 'ripper1' 2 | 3 | ripper = XmlRipper.new do |r| ##(main 4 | r.on_path( '/document/author' ) { |a| puts a.text } ##+doc_author 5 | r.on_path( '/document/chapter/title' ) { |t| puts t.text } 6 | end 7 | 8 | ripper.run( 'fellowship.xml' ) ##main) 9 | -------------------------------------------------------------------------------- /27/ripper2.rb: -------------------------------------------------------------------------------- 1 | require "ripper1" 2 | 3 | class XmlRipper ##(main 4 | 5 | def initialize(&block) 6 | @before_action = proc {} 7 | @path_actions = {} 8 | @after_action = proc {} 9 | instance_eval( &block ) if block 10 | end 11 | 12 | # Rest of the class omitted... 13 | 14 | end ##main) 15 | 16 | -------------------------------------------------------------------------------- /27/ripper2_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ripper2' 2 | 3 | ripper = XmlRipper.new do ##(main 4 | on_path( '/document/author' ) do |author| 5 | author.text = 'J.R.R. Tolkien' 6 | end 7 | after { |doc| puts doc } 8 | end 9 | 10 | ripper.run( 'fellowship.xml' ) ##main) 11 | -------------------------------------------------------------------------------- /27/ripper2_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe "second ripper scripts" do 4 | 5 | it 'fix title example should work' do 6 | out = `ruby -I . ripper2_demo.rb` 7 | out.should match( /author>J.R.R. Tolkien/ ) 8 | end 9 | 10 | end 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /27/ripper3.rb: -------------------------------------------------------------------------------- 1 | require "ripper2" 2 | 3 | class XmlRipper ##(main 4 | 5 | def initialize_from_file( path ) 6 | instance_eval( File.read( path ) ) 7 | end 8 | 9 | # Rest of the class omitted... 10 | 11 | end ##main) 12 | 13 | -------------------------------------------------------------------------------- /27/ripper3_demo.rb: -------------------------------------------------------------------------------- 1 | require "ripper3" 2 | 3 | ripper = XmlRipper.new ##(main 4 | ripper.initialize_from_file( 'fix_author.ripper' ) 5 | ripper.run( 'fellowship.xml') ##main) 6 | -------------------------------------------------------------------------------- /27/ripper3_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe "second ripper scripts" do 4 | 5 | it 'fix title example should work' do 6 | out = `ruby -I . ripper3_demo.rb` 7 | out.should match( /author>J.R.R. Tolkien/ ) 8 | end 9 | 10 | end 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /27/ripper4.rb: -------------------------------------------------------------------------------- 1 | require "ripper3" 2 | 3 | class XmlRipper ##(main 4 | 5 | # Rest of the class omitted... 6 | 7 | def method_missing( name, *args, &block ) 8 | return super unless name.to_s =~ /on_.*/ 9 | parts = name.to_s.split( "_" ) 10 | parts.shift 11 | xpath = parts.join( '/' ) 12 | on_path( xpath, &block ) 13 | end 14 | end ##main) 15 | -------------------------------------------------------------------------------- /27/ripper4_main.rb: -------------------------------------------------------------------------------- 1 | require "ripper4" 2 | 3 | r = XmlRipper.new ##(main 4 | r.initialize_from_file( ARGV[0] ) 5 | r.run( ARGV[1] ) ##main) 6 | -------------------------------------------------------------------------------- /27/ripper4_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | describe 'xmlripper4' do 3 | 4 | it 'should work with the commented version' do 5 | out = `ruby -I . ripper4_main.rb on_doc_author.ripper fellowship.xml` 6 | out.should == "J. R. R. Tolken\n" 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /27/ripper5.rb: -------------------------------------------------------------------------------- 1 | require "ripper2" 2 | 3 | class XmlRipper ##(main 4 | 5 | def initialize_from_file( path ) 6 | instance_eval( File.read( path ), path ) 7 | end 8 | 9 | # Rest of the class omitted... 10 | 11 | end ##main) 12 | 13 | -------------------------------------------------------------------------------- /27/ripper5_main.rb: -------------------------------------------------------------------------------- 1 | require "ripper5" 2 | 3 | r = XmlRipper.new 4 | r.initialize_from_file( ARGV[0] ) 5 | r.run( ARGV[1] ) 6 | -------------------------------------------------------------------------------- /28/Rakefile: -------------------------------------------------------------------------------- 1 | 2 | Targets = %w{ fellowship.xml spec out.odt} 3 | 4 | require '../utils/tasks.rb' 5 | 6 | CLEAN.include('fellowship.xml') 7 | 8 | 9 | file 'fellowship.xml' do |f| 10 | cp '../27/fellowship.xml', '.' 11 | end 12 | 13 | task :init => 'fellowship.xml' 14 | -------------------------------------------------------------------------------- /28/bad_delete.ezr: -------------------------------------------------------------------------------- 1 | 2 | delete 3 | 4 | -------------------------------------------------------------------------------- /28/bad_examples.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | shared_examples_for "it has decent error handling" do 4 | it 'should blow up on a bad print' do 5 | out = error_message_of { EzRipper.new( 'bad_print.ezr' ).run( 'fellowship.xml' ) } 6 | out.should match( /Expected print / ) 7 | end 8 | 9 | it 'should blow up on a bad delete' do 10 | out = error_message_of { EzRipper.new( 'bad_delete.ezr' ).run( 'fellowship.xml' ) } 11 | out.should match( /Expected delete / ) 12 | end 13 | 14 | it 'should blow up on a bad replace' do 15 | out = error_message_of { EzRipper.new( 'bad_replace.ezr' ).run( 'fellowship.xml' ) } 16 | out.should match( /Expected replace / ) 17 | end 18 | 19 | it 'should blow up on a bad delete' do 20 | out = error_message_of { EzRipper.new( 'bad_print_document.ezr' ).run( 'fellowship.xml' ) } 21 | out.should match( /Expected print_document/ ) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /28/bad_print.ezr: -------------------------------------------------------------------------------- 1 | print 2 | 3 | -------------------------------------------------------------------------------- /28/bad_print_document.ezr: -------------------------------------------------------------------------------- 1 | print_document aa bb cc dd 2 | 3 | -------------------------------------------------------------------------------- /28/bad_replace.ezr: -------------------------------------------------------------------------------- 1 | replace /document/author 2 | 3 | -------------------------------------------------------------------------------- /28/bad_statement.ezr: -------------------------------------------------------------------------------- 1 | foobar /document/author 2 | 3 | -------------------------------------------------------------------------------- /28/bad_upcase.ezr: -------------------------------------------------------------------------------- 1 | uppercase 2 | print_document 3 | -------------------------------------------------------------------------------- /28/comments.ezr: -------------------------------------------------------------------------------- 1 | # Lead comment 2 | 3 | uppercase document/author 4 | print_document 5 | 6 | # comment at the end 7 | -------------------------------------------------------------------------------- /28/common.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | require '../utils/rspec_utils' 3 | 4 | dir = File.dirname( __FILE__ ) 5 | $: << "#{dir}/../27" 6 | 7 | -------------------------------------------------------------------------------- /28/edit.ezr: -------------------------------------------------------------------------------- 1 | delete /document/published 2 | replace /document/author Tolkien 3 | print_document 4 | -------------------------------------------------------------------------------- /28/ex_1_spec.rb: -------------------------------------------------------------------------------- 1 | require 'common' 2 | require 'ripper4.rb' 3 | require 'ez_ripper1' 4 | 5 | require 'good_examples' 6 | 7 | describe EzRipper do 8 | it_should_behave_like "it handles correct ezr programs" 9 | end 10 | 11 | 12 | -------------------------------------------------------------------------------- /28/ex_2_spec.rb: -------------------------------------------------------------------------------- 1 | require 'common' 2 | require 'ez_ripper2.rb' 3 | require 'bad_examples' 4 | require 'good_examples' 5 | 6 | describe EzRipper do 7 | it_should_behave_like "it handles correct ezr programs" 8 | it_should_behave_like "it has decent error handling" 9 | end 10 | 11 | -------------------------------------------------------------------------------- /28/ex_3_spec.rb: -------------------------------------------------------------------------------- 1 | require 'common' 2 | require 'ez_ripper3.rb' 3 | require 'bad_examples' 4 | require 'good_examples' 5 | 6 | describe EzRipper do 7 | it 'should handle uppercase command' do 8 | EzRipper.new( 'upcase.ezr').run('fellowship.xml' ) 9 | out = output_of { EzRipper.new( 'upcase.ezr').run('fellowship.xml' ) } 10 | out.should match( /FELLOWSHIP/ ) 11 | end 12 | 13 | it 'should handle a bad upcase command' do 14 | out = error_message_of { EzRipper.new( 'bad_upcase.ezr').run('fellowship.xml' ) } 15 | out.should match( /Expected uppercase / ) 16 | end 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /28/ex_4_spec.rb: -------------------------------------------------------------------------------- 1 | require 'common' 2 | require 'ez_ripper4.rb' 3 | 4 | describe EzRipper do 5 | it 'should handle comments' do 6 | out = output_of { EzRipper.new( 'comments.ezr').run('fellowship.xml' ) } 7 | out.should match( /TOL/ ) 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /28/ex_6_spec.rb: -------------------------------------------------------------------------------- 1 | require 'common' 2 | require 'ez_ripper6' 3 | 4 | 5 | describe 'EzRipper with execute command' do 6 | it 'should work as described in the book' do 7 | ezr = EzRipper.new( 'execute.ezr' ) 8 | output_of { ezr.run( 'fellowship.xml' ) }.should match( /author is.*Tol/m ) 9 | end 10 | end 11 | 12 | -------------------------------------------------------------------------------- /28/ex_erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'erb' 2 | require '../utils/rspec_utils' 3 | 4 | describe 'converting erb' do 5 | it 'should work as described in book' do 6 | template = File.read('example.erb') 7 | erb = ERB.new( template ) 8 | out = erb.result 9 | out.should match( /Today is/ ) 10 | File.write( 'example.erb.out', out ) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /28/ex_haml_spec.rb: -------------------------------------------------------------------------------- 1 | require 'haml' 2 | require '../utils/rspec_utils' 3 | 4 | describe 'converting haml' do 5 | it 'should work as described in book' do 6 | template = File.read('example.haml') 7 | haml_engine = Haml::Engine.new(template) 8 | out = haml_engine.render 9 | out.should match( /.*<\/html>/m ) 10 | out.should match( /.*<\/body>/m ) 11 | out.should match( /Today is/m ) 12 | File.write( 'example.html', out ) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /28/example.erb: -------------------------------------------------------------------------------- 1 | Today is <%= Time.new %> 2 | -------------------------------------------------------------------------------- /28/example.haml: -------------------------------------------------------------------------------- 1 | %html 2 | %body 3 | #main 4 | Today is 5 | = Time.new 6 | -------------------------------------------------------------------------------- /28/execute.ezr: -------------------------------------------------------------------------------- 1 | execute '/document/author' 'puts "the author is #{el.text}"' 2 | -------------------------------------------------------------------------------- /28/ez_ripper1_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper1.rb' 2 | 3 | 4 | ezr = EzRipper.new( 'author.ezr' ) 5 | puts "running" 6 | ezr.run( 'fellowship.xml' ) 7 | 8 | -------------------------------------------------------------------------------- /28/ez_ripper2_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper2.rb' 2 | 3 | 4 | ezr = EzRipper.new( 'author.ezr' ) 5 | puts "running" 6 | ezr.run( 'fellowship.xml' ) 7 | 8 | -------------------------------------------------------------------------------- /28/ez_ripper3.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper2' 2 | 3 | class EzRipper 4 | 5 | # Most of the class omitted... 6 | 7 | def parse_statement( statement ) 8 | tokens = statement.strip.split 9 | return if tokens.empty? 10 | 11 | case tokens.first 12 | 13 | when 'uppercase' ##(uppercase 14 | raise "Expected uppercase " unless tokens.size == 2 15 | @ripper.on_path( tokens[1] ) { |el| el.text = el.text.upcase } ##uppercase) 16 | 17 | when 'print_document' 18 | raise "print_document does not take any arguments" unless tokens.size == 1 19 | @ripper.after do |doc| 20 | puts doc 21 | end 22 | 23 | else 24 | raise "Unknown keyword: #{tokens.first}" 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /28/ez_ripper3_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper3' 2 | 3 | 4 | ezr = EzRipper.new( 'upcase.ezr' ) 5 | ezr.run( 'fellowship.xml' ) 6 | 7 | -------------------------------------------------------------------------------- /28/ez_ripper4.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper2' 2 | 3 | class EzRipper 4 | 5 | # Most of the class omitted... 6 | 7 | def parse_statement( statement ) ##(comment 8 | statement = statement.sub( /#.*/, '' ) 9 | tokens = statement.strip.split 10 | return if tokens.empty? ##comment) 11 | 12 | case tokens.first 13 | 14 | when 'uppercase' ##(uppercase 15 | raise "Expected uppercase " unless tokens.size == 2 16 | @ripper.on_path( tokens[1] ) { |el| el.text = el.text.upcase } ##uppercase) 17 | 18 | when 'print_document' 19 | raise "print_document does not take any arguments" unless tokens.size == 1 20 | @ripper.after do |doc| 21 | puts doc 22 | end 23 | 24 | else 25 | raise "Unknown keyword: #{tokens.first}" 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /28/ez_ripper4_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper4' 2 | 3 | 4 | ezr = EzRipper.new( 'all.ezr' ) 5 | puts "running" 6 | ezr.run( 'fellowship.xml' ) 7 | 8 | -------------------------------------------------------------------------------- /28/ez_ripper5.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper2' 2 | 3 | class EzRipper 4 | 5 | # Most of the class omitted... 6 | 7 | def parse_statement( statement ) ##(main 8 | 9 | statement = statement.sub( /#.*/, '' ) 10 | 11 | case statement.strip 12 | when '' 13 | # Skip blank lines 14 | 15 | when /print\s+'(.*?)'/ 16 | @ripper.on_path( $1 ) do |el| 17 | puts el.text 18 | end 19 | 20 | when /delete\s+'(.*?)'/ 21 | @ripper.on_path( $1 ) { |el| el.remove } 22 | 23 | when /replace\s+'(.*?)'\s+'(.*?)'$/ 24 | @ripper.on_path( $1 ) { |el| el.text = $2 } 25 | 26 | when /uppercase\s+'(.*?)'/ 27 | @ripper.on_path( $1 ) { |el| el.text = el.text.upcase } 28 | 29 | when /print_document/ 30 | @ripper.after do |doc| 31 | puts doc 32 | end 33 | 34 | else 35 | raise "Don't know what to do with: #{statement}" 36 | end 37 | end ##main) 38 | end 39 | 40 | -------------------------------------------------------------------------------- /28/ez_ripper5_demo.rb: -------------------------------------------------------------------------------- 1 | require 'ez_ripper4' 2 | 3 | 4 | ezr = EzRipper.new( 'all.ezr' ) 5 | puts "running" 6 | ezr.run( 'fellowship.xml' ) 7 | 8 | -------------------------------------------------------------------------------- /28/ez_ripper6.rb: -------------------------------------------------------------------------------- 1 | ## 2 | require 'ez_ripper2' 3 | 4 | class EzRipper 5 | 6 | # Most of the class omitted... 7 | 8 | def parse_statement( statement ) 9 | case statement.strip 10 | when '' 11 | # Skip blank lines 12 | 13 | when /^\W*#/ 14 | # Skip comments 15 | 16 | when /execute\s+'(.*?)'\s+'(.*?)'$/ ##(main 17 | @ripper.on_path( $1 ) { |el| eval( $2 ) } ##main) 18 | 19 | when /print\s+'(.*?)'/ 20 | @ripper.on_path( $1 ) do |el| 21 | puts el.text 22 | end 23 | 24 | when /delete\s+'(.*?)'/ 25 | @ripper.on_path( $1 ) { |el| el.remove } 26 | 27 | when /replace\s+'(.*?)'\s+'(.*?)'$/ 28 | @ripper.on_path( $1 ) { |el| el.text = $2 } 29 | 30 | when /uppercase\s+'(.*?)'/ 31 | @ripper.on_path( $1 ) { |el| el.text = el.text.upcase } 32 | 33 | when /print_document/ 34 | @ripper.after do |doc| 35 | puts doc 36 | end 37 | 38 | else 39 | raise "Don't know what to do with: #{statement}" 40 | end 41 | end 42 | end 43 | 44 | -------------------------------------------------------------------------------- /28/ez_ripper_statement.tt: -------------------------------------------------------------------------------- 1 | grammar EzRipperStatement 2 | 3 | rule statement 4 | comment/delete_statement/replace_statement/print_statement 5 | end 6 | 7 | rule comment 8 | "#" .* 9 | end 10 | 11 | rule delete_statement 12 | "delete" sp quoted_argument sp 13 | end 14 | 15 | rule replace_statement 16 | "replace" sp quoted_argument sp quoted_argument sp 17 | end 18 | 19 | rule print_statement 20 | "filter" sp quoted_argument sp 21 | end 22 | 23 | rule quoted_argument 24 | "'" argument "'" 25 | end 26 | 27 | rule argument 28 | (!"'" . )* 29 | end 30 | 31 | rule sp 32 | [ \t\n]* 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /28/ez_ripper_statement_spec.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | 3 | describe 'EzRipperStatementParser' do 4 | 5 | it 'should work as advertised' do 6 | require 'treetop' ##(main 7 | require 'ez_ripper_statement' 8 | 9 | statement = "replace '/document/author' 'Russ Olsen'" 10 | parser = EzRipperStatementParser.new 11 | parse_tree = parser.parse( statement ) ##main) 12 | 13 | parse_tree.should_not == nil 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /28/ezr.rb: -------------------------------------------------------------------------------- 1 | require 'ezripper1.rb' 2 | 3 | 4 | ezr = EZRipper.new( ARGV[0] ) 5 | ezr.run( ARGV[1] ) 6 | 7 | -------------------------------------------------------------------------------- /28/good_examples.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | shared_examples_for "it handles correct ezr programs" do 4 | it 'print author example should work' do 5 | out = output_of { EzRipper.new( 'print_author.ezr').run('fellowship.xml' ) } 6 | out.should match( /Tol/ ) 7 | end 8 | 9 | it 'replace delete example should work' do 10 | FileUtils.cp 'replace_delete.ezr', 'temp.ezr' 11 | File.open( 'temp.ezr', 'a' ) {|f| f.puts 'print_document' } 12 | 13 | out = output_of { EzRipper.new('temp.ezr').run('fellowship.xml') } 14 | out.should match( /Tolkien/m ) 15 | end 16 | 17 | it 'replace delete print example should work' do 18 | out = output_of { 19 | EzRipper.new( 'edit.ezr').run('fellowship.xml' ) ##+edit_ezr 20 | } 21 | out.should match( /Tol/ ) 22 | out.should_not match( /published/ ) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /28/print_author.ezr: -------------------------------------------------------------------------------- 1 | print /document/author 2 | -------------------------------------------------------------------------------- /28/replace_delete.ezr: -------------------------------------------------------------------------------- 1 | delete /document/published 2 | replace /document/author Tolkien 3 | -------------------------------------------------------------------------------- /28/temp.ezr: -------------------------------------------------------------------------------- 1 | delete /document/published 2 | replace /document/author Tolkien 3 | print_document 4 | -------------------------------------------------------------------------------- /28/upcase.ezr: -------------------------------------------------------------------------------- 1 | uppercase /document/title 2 | print_document 3 | -------------------------------------------------------------------------------- /29/BachGavotteShort.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russolsen/eloquent_ruby_code/a7e2a638ef9920a6f71d53529ac7801b6b594b93/29/BachGavotteShort.mp3 -------------------------------------------------------------------------------- /29/README.md: -------------------------------------------------------------------------------- 1 | The info in this directory is mostly outdated. 2 | -------------------------------------------------------------------------------- /29/Rakefile: -------------------------------------------------------------------------------- 1 | 2 | task :default do 3 | puts "The code in this directory is mostly outdated" 4 | end 5 | 6 | task :clean do 7 | puts "This is as clean as it gets" 8 | end 9 | -------------------------------------------------------------------------------- /29/document_simple/Rakefile: -------------------------------------------------------------------------------- 1 | require 'spec/rake/spectask' 2 | require 'rake/gempackagetask' 3 | 4 | task :default => [ :spec, :gem ] 5 | 6 | Spec::Rake::SpecTask.new do |t| 7 | t.spec_files = FileList['spec/**/*_spec.rb'] 8 | end 9 | 10 | gem_spec = Gem::Specification.new do |s| 11 | s.name = "document" 12 | s.version = "1.0.1" 13 | s.authors = ["Russ Olsen"] 14 | s.date = %q{2010-01-01} 15 | s.description = 'Document - Simple document class' 16 | s.summary = s.description 17 | s.email = 'russ@russolsen.com' 18 | s.files = [ 'README', 'lib/document.rb', 'spec/document_spec.rb' ] 19 | s.homepage = 'http://www.russolsen.com' 20 | s.has_rdoc = true 21 | s.rubyforge_project = 'simple_document' 22 | end 23 | 24 | Rake::GemPackageTask.new( gem_spec ) do |t| 25 | t.need_zip = true 26 | end 27 | 28 | task :push => :gem do |t| 29 | sh "gem push pkg/#{gem_spec.name}-#{gem_spec.version}.gem" 30 | end 31 | -------------------------------------------------------------------------------- /29/document_simple/document.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = "document" 3 | s.version = "1.0.1" 4 | s.authors = ["Russ Olsen"] 5 | s.date = %q{2010-01-01} 6 | s.description = 'Document - Simple document class' 7 | s.summary = s.description 8 | s.email = 'russ@russolsen.com' 9 | s.files = ['README', 'lib/document.rb','spec/document_spec.rb'] 10 | s.homepage = 'http://www.russolsen.com' 11 | s.has_rdoc = true 12 | s.rubyforge_project = 'simple_document' 13 | end 14 | -------------------------------------------------------------------------------- /29/document_simple/foo.rb: -------------------------------------------------------------------------------- 1 | puts File.realname(File.dirname(__FILE__)) 2 | -------------------------------------------------------------------------------- /29/document_simple/hoe.rb: -------------------------------------------------------------------------------- 1 | puts "local hoe executed" 2 | -------------------------------------------------------------------------------- /29/document_simple/lib/document.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Document 4 | 5 | attr_accessor :title, :author, :content 6 | 7 | def initialize( title, author, content ) 8 | @title = title 9 | @author = author 10 | @content = content 11 | end 12 | 13 | def words 14 | @content.split 15 | end 16 | 17 | def word_count 18 | words.size 19 | end 20 | 21 | def average_word_length 22 | number_word_characters / word_count 23 | end 24 | 25 | def number_word_characters 26 | words.inject( 0 ) { |total, word| total += word.size } 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /29/document_simple/load_twice.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'hoe' 3 | dir = File.expand_path( File.dirname(__FILE__) ) 4 | require File.join( dir, 'hoe' ) 5 | -------------------------------------------------------------------------------- /29/document_simple/pkg/document-1.0.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russolsen/eloquent_ruby_code/a7e2a638ef9920a6f71d53529ac7801b6b594b93/29/document_simple/pkg/document-1.0.1.gem -------------------------------------------------------------------------------- /29/document_simple/spec/document_spec.rb: -------------------------------------------------------------------------------- 1 | $: << "#{File.dirname(__FILE__)}/../lib" 2 | 3 | require 'document' 4 | 5 | describe Document do 6 | 7 | before :each do 8 | @document = Document.new( 'test', 'russ', 'nothing' ) 9 | end 10 | 11 | it "should hold onto the title, author and content" do 12 | @document.title.should == 'test' 13 | @document.author.should == 'russ' 14 | @document.content.should == 'nothing' 15 | end 16 | 17 | it "should be able to split content into words" do 18 | @document.content = 'the rain in spain' 19 | @document.words.should == %w{ the rain in spain } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /29/ex_1_mp3info_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'Mp3Info' do 2 | 3 | it 'should work like the book says' do 4 | require 'mp3info' ##(main 5 | 6 | Mp3Info.open( 'BachGavotteShort.mp3' ) do |info| 7 | puts "title: #{info.tag.title}" 8 | puts "artist: #{info.tag.artist}" 9 | puts "album: #{info.tag.album}" 10 | end ##main) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /29/ex_2_gem_cmds_spec.rb: -------------------------------------------------------------------------------- 1 | require '../utils/rspec_utils' 2 | 3 | describe 'gem command' do 4 | 5 | it 'should have an install cmd' do 6 | eval "`#{File.read('gem.install.cmd')}`" 7 | end 8 | 9 | it 'should install a specific gem version' do 10 | eval "`#{File.read('gem.install.04.cmd')}`" 11 | end 12 | 13 | it 'should install many gem version' do 14 | eval "`#{File.read('gem.install.many.cmd')}`" 15 | end 16 | 17 | it 'should have a list subcomment' do 18 | out = eval("`#{File.read('gem.list.cmd')}`") 19 | out.should match(/6\.12.*6\.9.*0\.4/m) 20 | File.write( 'versions.txt', out.breakup ) 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /29/ex_2_specific_version_spec.rb: -------------------------------------------------------------------------------- 1 | 2 | describe 'getting a specific version of a gem' do 3 | 4 | it 'should work like the books says' do 5 | gem 'ruby-mp3info', '=0.5' 6 | require 'mp3info' 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /29/file_test.rb: -------------------------------------------------------------------------------- 1 | p __FILE__ 2 | -------------------------------------------------------------------------------- /29/gem.install.04.cmd: -------------------------------------------------------------------------------- 1 | gem install --version 0.4 ruby-mp3info 2 | -------------------------------------------------------------------------------- /29/gem.install.cmd: -------------------------------------------------------------------------------- 1 | gem install ruby-mp3info 2 | -------------------------------------------------------------------------------- /29/gem.install.many.cmd: -------------------------------------------------------------------------------- 1 | gem install --version 0.5 ruby-mp3info 2 | gem install --version 0.5.1 ruby-mp3info 3 | gem install --version 0.6 ruby-mp3info 4 | -------------------------------------------------------------------------------- /29/gem.list.cmd: -------------------------------------------------------------------------------- 1 | gem list -a --remote ruby-mp3info 2 | -------------------------------------------------------------------------------- /29/versions.txt: -------------------------------------------------------------------------------- 1 | ruby-mp3info (0.8, 0.7.2, 0.7.1, 0.7, 0.6.16, 0.6.15, 2 | 0.6.14, 0.6.13, 0.6.12, 0.6.11, 0.6.10, 0.6.9, 0.6.8, 3 | 0.6.7, 0.6.6, 0.6.5, 0.6.4, 0.6.3, 0.6.2, 0.6.1, 0.6, 4 | 0.5.1, 0.5, 0.4) -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'rake' 4 | gem 'rspec' 5 | gem 'xml-simple' 6 | gem 'shoulda' 7 | gem 'text' 8 | gem 'mp3info' 9 | gem 'haml' 10 | gem 'treetop' 11 | gem 'test-unit' 12 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dirs = Dir['[0-9][0-9]'].sort 4 | 5 | def build_target( target ) 6 | Dirs.each do |dir| 7 | sh "cd #{dir}; rake #{target}" 8 | end 9 | end 10 | 11 | task :default do 12 | build_target( :default ) 13 | end 14 | 15 | task :sniff do 16 | build_target( :sniff ) 17 | end 18 | 19 | task :clean do 20 | build_target( :clean ) 21 | end 22 | -------------------------------------------------------------------------------- /code/doc1.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /code/doc2.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /code/doc3.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end 13 | 14 | def word_count 15 | words.size 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /code/doc4.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end 13 | 14 | def word_count 15 | words.size 16 | end 17 | 18 | def average_word_length 19 | all_words = words 20 | 21 | len = all_words.inject(0.0){ |total, word| word.size + total } 22 | len / all_words.size 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /code/doc_access.rb: -------------------------------------------------------------------------------- 1 | attr_accessor :title, :author, :content 2 | -------------------------------------------------------------------------------- /code/doc_avg_word_len.rb: -------------------------------------------------------------------------------- 1 | def average_word_length 2 | len = words.inject(0.0){ |total, word| word.size + total } 3 | len / words.size 4 | end 5 | -------------------------------------------------------------------------------- /code/doc_init.rb: -------------------------------------------------------------------------------- 1 | def initialize(title, author, content) 2 | @title = title 3 | @author = author 4 | @content = content 5 | end 6 | -------------------------------------------------------------------------------- /code/doc_word_count.rb: -------------------------------------------------------------------------------- 1 | def word_count 2 | words.size 3 | end 4 | -------------------------------------------------------------------------------- /code/doc_words.rb: -------------------------------------------------------------------------------- 1 | def words 2 | @content.split 3 | end 4 | -------------------------------------------------------------------------------- /code/document.rb: -------------------------------------------------------------------------------- 1 | class Document ##(simple_doc 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end ##simple_doc) 13 | 14 | def average_word_length ##(avg_word_len 15 | all_words = words 16 | 17 | len = all_words.inject(0.0){ |total, word| word.size + total } 18 | len / all_words.size 19 | end ##avg_word_len) 20 | end ##+simple_doc 21 | -------------------------------------------------------------------------------- /code/simple_doc.rb: -------------------------------------------------------------------------------- 1 | class Document 2 | attr_accessor :title, :author, :content 3 | 4 | def initialize(title, author, content) 5 | @title = title 6 | @author = author 7 | @content = content 8 | end 9 | 10 | def words 11 | @content.split 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /rvmrc.example: -------------------------------------------------------------------------------- 1 | rvm use 1.9.3-p327@er --create 2 | -------------------------------------------------------------------------------- /utils/rspec_utils.rb: -------------------------------------------------------------------------------- 1 | require 'stringio' 2 | require 'pp' 3 | 4 | def output_of( &block ) 5 | output = StringIO.new 6 | $stdout = output 7 | begin 8 | block.call 9 | ensure 10 | $stdout = STDOUT 11 | end 12 | output.string 13 | end 14 | 15 | def error_message_of( &block ) 16 | begin 17 | block.call 18 | fail( "did not throw an exception" ) 19 | rescue 20 | return $!.message 21 | end 22 | end 23 | 24 | class String 25 | def breakup 26 | bits = self.split 27 | result = [''] 28 | bits.each do | bit | 29 | result << '' if result.last.size > 50 30 | result.last << bit 31 | result.last << ' ' 32 | end 33 | result.join("\n") 34 | end 35 | end 36 | 37 | class File 38 | def self.write( path, string ) 39 | File.open( path, 'w' ) {|f| f.print(string)} 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /utils/tasks.rb: -------------------------------------------------------------------------------- 1 | require 'rake' 2 | require 'rake/clean' 3 | require 'rspec/core/rake_task' 4 | require 'pathname' 5 | 6 | desc "Run all examples" 7 | task :spec do |t| 8 | Dir['*_spec.rb'].sort.each do |f| 9 | puts "Spec'ing #{f}" 10 | sh "rspec -I . #{f}" 11 | end 12 | end 13 | 14 | task :init 15 | 16 | task :default => %w{init spec} 17 | 18 | task :irb do 19 | sh "irb -I ." 20 | end 21 | --------------------------------------------------------------------------------