`
simohayha
  • 浏览: 1386441 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

一个简单的ruby Metaprogram的例子

    博客分类:
  • ruby
阅读更多
比如下面一个文件 people.txt

引用
name,age,weight,height
"Smith, John", 35, 175, "5'10"
"Ford, Anne", 49, 142, "5'4"
"Taylor, Burt", 55, 173, "5'10"
"Zubrin, Candace", 23, 133, "5'6"


我们的目标是什么呢?我们的目标就是实现类似于Rails中的Builder模块所做的事情,假设我们第二行数据 对象为a,那么我们可以通过a.name,a.age等等来得到他所对应的值:

class DataRecord    
      def self.make(file_name)
        data = File.new(file_name)
        header = data.gets.chomp
        data.close
#首先得到文件名,然后根据文件名动态的创建此文件对应的类
        class_name = File.basename(file_name,".txt").capitalize  
        klass = Object.const_set(class_name,Class.new)
        names = header.split(",")
#设置实例变量,并且将实例变量赋值
        klass.class_eval do
          attr_accessor *names
          define_method(:initialize) do |*values| 
            names.each_with_index do |name,i| 
              instance_variable_set("@"+name, values[i])
            end
          end   
#当put时能打印出显示更好的结果
          define_method(:to_s) do
            str = "<#{self.class}:"
            names.each {|name| str << " #{name}=#{self.send(name)}" }
            str + ">"
          end
          alias_method :inspect, :to_s
        end   
#读取数据然后将每一行数据都放进一个数组
        def klass.read
          array = []
          data = File.new(self.to_s.downcase+".txt")
          data.gets
          data.each do |line| 
            line.chomp!   
            values = eval("[#{line}]")
            array << self.new(*values)
          end
          data.close
          array
        end  
        klass
      end  
end

DataRecord.make("people.txt")
list = People.read   

p list[1].name 
p list[1].age  


分享到:
评论
3 楼 ahtest 2014-06-30  
赞一下~~
2 楼 java-admin 2011-10-09  
貌似这行出错了 :
instance_variable_set("@"+name, values[i])

我的环境是:
jruby 1.6.2 (ruby-1.8.7-p330) (2011-05-23 e2ea975) (Java HotSpot(TM) Client VM 1.6.0_26) [Windows XP-x86-java]
1 楼 dennis_zane 2008-03-04  
很好的例子

相关推荐

Global site tag (gtag.js) - Google Analytics