view 1-Ruby/acts_as_csv_module-irb.output @ 27:2ea3b5e9b41b

Implement day 3 self-study extensions: * `each` method to iterate over rows * `method_missing` to handle ".header_name" as value retrieval
author IBBoard <dev@ibboard.co.uk>
date Tue, 05 Sep 2017 20:24:03 +0100
parents
children
line wrap: on
line source

acts_as_csv_module.rb(main):001:0> #---
acts_as_csv_module.rb(main):002:0* # Excerpted from "Seven Languages in Seven Weeks",
acts_as_csv_module.rb(main):003:0* # published by The Pragmatic Bookshelf.
acts_as_csv_module.rb(main):004:0* # Copyrights apply to this code. It may not be used to create training material, 
acts_as_csv_module.rb(main):005:0* # courses, books, articles, and the like. Contact us if you are in doubt.
acts_as_csv_module.rb(main):006:0* # We make no guarantees that this code is fit for any purpose. 
acts_as_csv_module.rb(main):007:0* # Visit http://www.pragmaticprogrammer.com/titles/btlang for more book information.
acts_as_csv_module.rb(main):008:0* #---
acts_as_csv_module.rb(main):009:0* module ActsAsCsv
acts_as_csv_module.rb(main):010:1>   def self.included(base)
acts_as_csv_module.rb(main):011:2>     base.extend ClassMethods
acts_as_csv_module.rb(main):012:2>     # The book doesn't do this, but it is possible to add the methods
acts_as_csv_module.rb(main):013:2*     # without having the inheriting class call a second function to do it
acts_as_csv_module.rb(main):014:2*     base.acts_as_csv
acts_as_csv_module.rb(main):015:2>   end
acts_as_csv_module.rb(main):016:1>   
acts_as_csv_module.rb(main):017:1*   module ClassMethods
acts_as_csv_module.rb(main):018:2>     def acts_as_csv
acts_as_csv_module.rb(main):019:3>       include InstanceMethods
acts_as_csv_module.rb(main):020:3>     end
acts_as_csv_module.rb(main):021:2>   end
acts_as_csv_module.rb(main):022:1>   
acts_as_csv_module.rb(main):023:1*   module InstanceMethods  
acts_as_csv_module.rb(main):024:2> 
acts_as_csv_module.rb(main):025:2*     def read
acts_as_csv_module.rb(main):026:3>       self.csv_contents = []
acts_as_csv_module.rb(main):027:3>       filename = self.class.to_s.downcase + '.txt'
acts_as_csv_module.rb(main):028:3>       file = File.new(filename)
acts_as_csv_module.rb(main):029:3>       @headers = file.gets.chomp.split(', ')
acts_as_csv_module.rb(main):030:3> 
acts_as_csv_module.rb(main):031:3*       file.each do |row|
acts_as_csv_module.rb(main):032:4*         csv_row = CsvRow.new(headers, row.chomp.split(', '))
acts_as_csv_module.rb(main):033:4>         @csv_contents << csv_row
acts_as_csv_module.rb(main):034:4>       end
acts_as_csv_module.rb(main):035:3>     end
acts_as_csv_module.rb(main):036:2>     
acts_as_csv_module.rb(main):037:2*     attr_accessor :headers, :csv_contents
acts_as_csv_module.rb(main):038:2>     def initialize
acts_as_csv_module.rb(main):039:3>       read
acts_as_csv_module.rb(main):040:3>     end
acts_as_csv_module.rb(main):041:2> 
acts_as_csv_module.rb(main):042:2*     def each()
acts_as_csv_module.rb(main):043:3>       self.csv_contents.each { |row| yield row }
acts_as_csv_module.rb(main):044:3>     end
acts_as_csv_module.rb(main):045:2>   end
acts_as_csv_module.rb(main):046:1> end
=> :each
acts_as_csv_module.rb(main):047:0> 
acts_as_csv_module.rb(main):048:0* class RubyCsv  # no inheritance! You can mix it in
acts_as_csv_module.rb(main):049:1>   include ActsAsCsv
acts_as_csv_module.rb(main):050:1>   # Also, nothing to do beyond the "include" - it automatically defines the methods!
acts_as_csv_module.rb(main):051:1* end
=> RubyCsv
acts_as_csv_module.rb(main):052:0> 
acts_as_csv_module.rb(main):053:0* class CsvRow
acts_as_csv_module.rb(main):054:1>   attr_reader :values
acts_as_csv_module.rb(main):055:1> 
acts_as_csv_module.rb(main):056:1*   def initialize(headers, values)
acts_as_csv_module.rb(main):057:2>     @values = Hash[headers.zip(values)]
acts_as_csv_module.rb(main):058:2>   end
acts_as_csv_module.rb(main):059:1> 
acts_as_csv_module.rb(main):060:1*   def method_missing(methId, *args)
acts_as_csv_module.rb(main):061:2>     str = methId.id2name
acts_as_csv_module.rb(main):062:2>     if @values.key?(str)
acts_as_csv_module.rb(main):063:3>       return @values[str]
acts_as_csv_module.rb(main):064:3>     else
acts_as_csv_module.rb(main):065:3*       super.method_missing(methId)
acts_as_csv_module.rb(main):066:3>     end
acts_as_csv_module.rb(main):067:2>   end
acts_as_csv_module.rb(main):068:1> end
=> :method_missing
acts_as_csv_module.rb(main):069:0> 
acts_as_csv_module.rb(main):070:0* m = RubyCsv.new
=> #<RubyCsv:0x0000000212caf8 @csv_contents=[#<CsvRow:0x0000000212c558 @values={"first"=>"Yukihiro", "last"=>"Matsumoto", "country"=>"Japan"}>, #<CsvRow:0x0000000212c170 @values={"first"=>"Bruce", "last"=>"Tate", "country"=>"USA"}>], @headers=["first", "last", "country"]>
acts_as_csv_module.rb(main):071:0> puts m.headers.inspect
["first", "last", "country"]
=> nil
acts_as_csv_module.rb(main):072:0> puts m.csv_contents.inspect
[#<CsvRow:0x0000000212c558 @values={"first"=>"Yukihiro", "last"=>"Matsumoto", "country"=>"Japan"}>, #<CsvRow:0x0000000212c170 @values={"first"=>"Bruce", "last"=>"Tate", "country"=>"USA"}>]
=> nil
acts_as_csv_module.rb(main):073:0> # Use method_missing to implement heading-as-a-method
acts_as_csv_module.rb(main):074:0* puts m.csv_contents[0].country
Japan
=> nil
acts_as_csv_module.rb(main):075:0> # And show that we still get normal failure behaviour
acts_as_csv_module.rb(main):076:0* puts m.csv_contents[0].Country
NoMethodError: undefined method `Country' for #<CsvRow:0x0000000212c558>
	from acts_as_csv_module.rb:65:in `method_missing'
	from acts_as_csv_module.rb:76
	from /usr/bin/irb:11:in `<main>'
acts_as_csv_module.rb(main):077:0> 
acts_as_csv_module.rb(main):078:0* 
acts_as_csv_module.rb(main):078:0>