2013年2月11日月曜日

7つの言語7つの世界 [Ruby 3日目]


Ruby3日目

今回はメタプログラミングの話が主。RubyOnRailsにも興味があるので気になる話。
しかし、概要をサラッと流されているので深くは理解できず。
ただ、method_missingの話はおもしろい。
いかにRubyがプログラマに自由を与えているかのいい例だと思う。
(実際にこんなトリッキーな手法を使うかどうかは置いておいて。。。)
エラーの動作まで書き換えられる思想はすごい。

試してみよう

eachメソッドがCsvRowオブジェクトを返すようにCSVアプリケーションを変更せよ。そのCsvRowのmethod_missingを使って与えられた見出しの列を返すようにせよ。


#!/usr/bin/ruby                                        
                                                       
module ActsAsCsv                                       
                                                       
  def self.included(base)                              
    base.extend ClassMethods                           
  end                                                  
                                                       
                                                       
  module ClassMethods                                  
    def acts_as_csv                                    
      include InstanceMethods                          
    end                                                
  end                                                  
                                                       
  module InstanceMethods                               
                                                       
    def each                                           
      @csv_contents.each do |contents|                 
        yield contents                                 
      end                                              
    end                                                
                                                       
    def read                                           
      @csv_contents = []                               
      filename = self.class.to_s.downcase + '.txt'     
      file = File.new(filename)                        
      @headers = file.gets.chomp.split(', ')           
      file.each do |row|                               
        @csv_contents << CsvRow.new(row.chomp.split(',\
 '), @headers)                                         
      end                                              
    end                                                
                                                       
    attr_accessor :headers, :csv_contents              
                                                       
    def initialize                                     
      read                                             
    end                                                
  end                                                  
end

class CsvRow                                           
  def initialize( content, headers )                   
    @content = content                                 
    @headers = headers                                 
  end                                                  
  def method_missing(name, *args)                      
    idx = @headers.index(name.to_s)                    
    if idx != nil                                      
      @content[idx]                                    
    end                                                
  end                                                  
end                                                    
                                                       
class RubyCsv                                          
  include ActsAsCsv                                    
  acts_as_csv                                          
end                                                    
                                                       
m = RubyCsv.new                                        
m.each{|row|puts row.one} 



うえでは、method_missingはトリッキーとかいたけど、
こうやって見てみるとユーザ側のコードはかっこいいかも。
結局フレームワーク側で多少トリッキーなコードを書いても
ユーザのコードが見やすく生産性が上がればOKと言う発想なのかな?

0 件のコメント:

コメントを投稿