This morning, after 10 minutes struggle of do or do not follow the
self study section. Just spend several hours of searching, coding and
debugging, finally I got the following ruby script that is able to pass
the self study excise.
diff -r 9efeca9bd507 learning/ruby/acts_as_csv_module.rb
--- a/learning/ruby/acts_as_csv_module.rb Tue Feb 07 15:13:11 2017 +0800
+++ b/learning/ruby/acts_as_csv_module.rb Tue Feb 07 15:13:49 2017 +0800
@@ -1,32 +1,90 @@
module ActsAsCsv
+
def self.included(base)
base.extend ClassMethods
end
+
module ClassMethods
+
def acts_as_csv
include InstanceMethods
end
+
+ def acts_as_enumerable
+ include Enumerable
+ end
end
+
module InstanceMethods
+
def read
@csv_contents = []
filename = self.class.to_s.downcase + '.txt'
file = File.new(filename)
- @headers = file.gets.chomp.split(', ' )
+ CsvRow.headers = file.gets.chomp.split(', ' )
+
+ # puts "CsvRow.headers is #{CsvRow.headers}"
file.each do |row|
- @csv_contents << row.chomp.split(', ' )
+ csvrow = CsvRow.new
+ csvrow.row_content = row.chomp.split(', ' )
+
+ # puts "csvrow is #{csvrow.row_content}"
+ @csv_contents << csvrow
end
end
- attr_accessor :headers, :csv_contents
+
+ attr_accessor :csv_contents
+
def initialize
read
end
+
+ def each(&block)
+ # puts "csv_contents.each is #{@csv_contents.each}"
+ @csv_contents.each(&block)
+ end
+
end
end
+
class RubyCsv # no inheritance! You can mix it in
include ActsAsCsv
acts_as_csv
+ acts_as_enumerable
end
-m = RubyCsv.new
-puts m.headers.inspect
-puts m.csv_contents.inspect
+
+class CsvRow
+ @@header_indexes = {}
+
+ def method_missing name, *args
+ @row_content[@@header_indexes[name.to_s]]
+ end
+
+ attr_accessor :row_content
+
+ def initialize
+ @row_content = []
+ end
+
+ def self.headers=(h)
+ @@headers = h
+
+ # puts "h is #{h}"
+ h.each_index {|i| @@header_indexes[h[i]] = i}
+ # puts "@@header_indexes is #{@@header_indexes}"
+ end
+
+ def self.headers
+ @@headers
+ end
+end
+
+
+# m = RubyCsv.new
+# puts m.headers.inspect
+# puts m.csv_contents.inspect
+
+csv = RubyCsv.new
+
+# puts "csv_contents is #{csv.csv_contents}"
+csv.each {|row| puts row.one}Ruby feature learned
- Class variable is defined and accessed with “double at” prefix
@@. - Class accessor must be defined with
self.prefix, otherwise the result method will be instance accessor, I was confused by the complex syntax sugar used in the link. - Array has convenient
.each_indexmethod that will save you lots of type. eachmethod have to be defined aseach(&block)to be able to work, and the insideeachbeing invoked should also be invoked as.each(&block)for the block to be passed into it.attr_accessorwill generate ruby specific getter and setters codes for decorated attributes(have to be specified in the form of:rubysymbol).
评论
发表评论