使用ruby元编程的实例

来源:爱站网时间:2020-11-17编辑:网友分享
我们在ruby编程中经常会使用到很多ruby的语言特性,但是也有很多用户们不知道怎么使用ruby元编程,那么下面我们就一起去看看使用ruby元编程的实例。

我们在ruby编程中经常会使用到很多ruby的语言特性,但是也有很多用户们不知道怎么使用ruby元编程,那么下面我们就一起去看看使用ruby元编程的实例。
分享几个在实际项目中用到的场景,能力有限,如果有更优方案,请留言给我:)

rpc接口模板化——使用eval、alias、defind_method

require 'rack/rpc'

class Server  :hello_world
end

上面是一个rpc server,编写一个函数,调用rpc命令进行注册。

采用define_method、eval、alias方法,可以实现一个判断rpc/目录下的*.rb文件,进行加载和rpc接口注册的功能,实现代码如下:

module RPC
  require 'rack/rpc'
  #require rpc/*.rb文件
  Dir.glob(File.join(File.dirname(__FILE__), 'rpc', "*.rb")) do |file|
   require file
  end
  class Runner  "#{rpc_class.downcase}_#{rpc_name}".to_sym

     #添加到全局变量,汇总所有的rpc方法
     @@rpc_list  :help

  end
 end #RPC

 

完成上述功能后,可以非常方便的开发rpc接口,例如下面这个IP地址增、删、查的代码,注册ip.list, ip.add和ip.del方法:

module RPC
  module Ip
   #RPC_LIST used for regsiter rpc_call
   RPC_LIST = %w(list add del)

   def list
    $white_lists
   end   

   def add(ip) 
    if ip =~ /^((25[0-5]|2[0-4]\d|[0-1]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[0-1]?\d\d?)$/
     $white_lists 

 

DSL——使用instance_eval

instance_eval是ruby语言中的瑞士军刀,特别是支持DSL方面。
我们来看一下chef(一个开源的自动化部署工具)中设置文件模板的API:

复制代码 代码如下:

    template "/path/to/file.conf" do
      source "file.conf.erb"
      owner  "wilbur"
      mode   "0744"
    end


上述代码中,source、owner、mode需要从外部block,传递到template内部的block中,为了实现该目的,采用了instance_eval代码如下:

 

  class ChefDSL
   def template(path, &block)
    TemplateDSL.new(path, &block)
   end
  end

  class TemplateDSL
   def initialize(path, &block)
    @path = path
    instance_eval &block
   end

   def source(source); @source = source; end
   def owner(owner);  @owner = owner; end
   def mode(mode);   @mode  = mode;  end
  end

 

上面这个小技巧使得TemplateDSL对象可以应用block,和在自己的scope一样。block可以访问和调用TemplateDSL中的变量和方法。

如果没有使用instance_eval,如下面的代码,ruby就会抛出一个NoMethodError,因为source、owner、mode无法在block中被访问到。

复制代码 代码如下:

    class TemplateDSL
      def initialize(path, &block)
        @path = path
        block.call
      end
    end

 

当然也可以使用yeild传递变量的方式实现,但没有instance_eval简洁和灵活。

命令行交互——使用instance_eval

命令行交互,可以采用highline这个gem.
但highline在有些方面不能满足我的需求,比如类似上面介绍的chef template功能,达到的效果如下,大大简化了重复代码:

复制代码 代码如下:

        #检查frigga fail,询问是否继续
        Tip.ask frigga_fail? do
          banner "Check some frigga failed, skip failed host and continue deploy?"
          on :yes
          on :quit do
            raise Odin::TipQuitExcption
          end
        end
        ...

 

        #运行时显示结果如下:
        Check some frigga failed, skip failed host and continue deploy? [yes/quit]
        #输入yes继续,输入quit退出

 

实现代码如下:

 require 'colorize'
 class Tip
  def self.ask(stat = true, &block)
   new(&block).ret if stat == true
  end

  attr_reader :ret
  def initialize(&block)
   @opt = []
   @caller = {}
   @banner = ""
   @ret = false
   self.instance_eval(&block)
   print "#{@banner} [#{@opt.join('/')}]: ".light_yellow
   loop do
    x = gets.chomp.strip.to_sym
    if @opt.include?(x)
     @ret = ( @caller[x].call if @caller.key?(x) )
     if @ret == :retry
      print "\n#{@banner} [#{@opt.join('/')}]: ".light_yellow
      next
     else
      return @ret
     end
    else
     print "input error, please enter [#{@opt.join('/')}]: ".light_yellow
    end
   end

  end

  def on(opt, &block)
   @opt 

以上就是小编介绍使用ruby元编程的实例,文中包含了用eval、alias、defind_method、instance_eval等实际使用例子。

上一篇:ruby实现异步文件下载HttpServer的教程

下一篇:如何使用qwandry

您可能感兴趣的文章

相关阅读

热门软件源码

最新软件源码下载