亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Ruby > 正文

ruby元編程實際使用實例

2020-03-29 12:08:58
字體:
來源:轉載
供稿:網友

很喜歡ruby元編程,puppet和chef用到了很多ruby的語言特性,來定義一個新的部署語言。
分享幾個在實際項目中用到的場景,能力有限,如果有更優方案,請留言給我:)

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

require 'rack/rpc'class Server < Rack::RPC::Server def hello_world  "Hello, world!" end rpc 'hello_world' => :hello_worldend

上面是一個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 < Rack::RPC::Server   #include rpc/*.rb and regsiter rpc call   #eg. rpc/god.rb  god.hello   @@rpc_list = []   Dir.glob(File.join(File.dirname(__FILE__), 'rpc', "*.rb")) do |file|    rpc_class = File.basename(file).split('.rb')[0].capitalize    rpc_list = []        #加載module下的方法到Runner這個類下面    eval "include Frigga::RPC::#{rpc_class}"    #獲取聲明的RPC接口    eval "rpc_list = Frigga::RPC::#{rpc_class}::RPC_LIST"    rpc_list.each do |rpc_name|     #alias一個新的rpc方法,叫old_xxxx_xxxx     eval "alias :old_#{rpc_class.downcase}_#{rpc_name} :#{rpc_name}"     #重新定義rpc方法,添加一行日志打印功能,然后再調用old_xxxx_xxxx rpc方法     define_method "#{rpc_class.downcase}_#{rpc_name}".to_sym do |*arg|      Logger.info "[#{request.ip}] called #{rpc_class.downcase}.#{rpc_name} #{arg.join(', ')}"      eval "old_#{rpc_class.downcase}_#{rpc_name} *arg"     end      #注冊RPC調用     rpc "#{rpc_class.downcase}.#{rpc_name}" => "#{rpc_class.downcase}_#{rpc_name}".to_sym     #添加到全局變量,匯總所有的rpc方法     @@rpc_list << "#{rpc_class.downcase}.#{rpc_name}"    end   end      def help    rpc_methods = (['help'] + @@rpc_list.sort).join("/n")   end   rpc "help" => :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 << ip     write_to_file     return "succ"    else     return "fail"    end   end   def del(ip)    if $white_lists.include?(ip)     $white_lists.delete ip     write_to_file     return "succ"    else     return "fail"    end       end   def write_to_file     File.open(IP_yml, "w") do |f|      $white_lists.uniq.each {|i| f << "- #{i}/n"}     end   end  end  end

 

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 << opt   @caller[opt] = block if block_given?  end  def banner(str)   @banner = str  end end


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本电影亚洲天堂| 亚洲欧洲在线免费| 在线观看精品国产视频| 久久精品欧美视频| 555www成人网| 国产精品吹潮在线观看| 国产美女久久精品| 亚洲а∨天堂久久精品喷水| 91网站在线看| 欧美日韩视频免费播放| 久久精品一区中文字幕| 中文字幕av日韩| 欧美成人午夜激情视频| 欧洲永久精品大片ww免费漫画| 九九精品在线视频| 在线视频一区二区| 人人爽久久涩噜噜噜网站| 国产精品久久久久久久久久久不卡| 日韩高清av一区二区三区| 精品久久久久久久久久久久久| www.亚洲免费视频| 国产91色在线免费| 日韩在线观看网站| 亚洲男人天堂九九视频| 91香蕉嫩草影院入口| 国产成人在线精品| 亚洲色无码播放| 国产精品69av| 成人免费网视频| 久久久久久久久久久亚洲| 成人日韩av在线| 免费91麻豆精品国产自产在线观看| 成人春色激情网| 精品自拍视频在线观看| 国产精品va在线播放我和闺蜜| 中文字幕精品www乱入免费视频| 成人国产精品一区二区| 国产精品九九久久久久久久| 日韩精品www| 国产日韩av高清| 久久久国产精彩视频美女艺术照福利| 国产精品久久久久aaaa九色| 亚洲第一网中文字幕| 欧美日韩精品在线视频| 亚洲国产欧美一区| 国产日韩欧美视频| 欧美大成色www永久网站婷| 亚洲激情视频网站| 另类色图亚洲色图| 日韩精品在线观看一区| 亚洲视频在线观看| 中日韩美女免费视频网址在线观看| 高潮白浆女日韩av免费看| 久久久久久伊人| 欧美日韩亚洲国产一区| 中文字幕久久亚洲| 成人字幕网zmw| 97精品国产91久久久久久| 国产欧美精品日韩精品| 亚洲福利在线观看| 日韩成人在线视频观看| 日韩高清免费观看| 国产欧美精品va在线观看| 亚洲精品videossex少妇| 亚洲国模精品私拍| 欧美性视频精品| 51久久精品夜色国产麻豆| 色妞久久福利网| 欧美精品18videosex性欧美| 成人精品久久av网站| 久久久噜久噜久久综合| 亚洲一区二区三区成人在线视频精品| 成人午夜在线视频一区| 久久久www成人免费精品| 性金发美女69hd大尺寸| 国产91精品黑色丝袜高跟鞋| 夜色77av精品影院| 欧美激情一区二区三区高清视频| 91久久国产精品91久久性色| 久久久久久国产精品| 日韩中文视频免费在线观看| 国产欧美一区二区白浆黑人| 91精品国产色综合| 国产97在线观看| 欧美日韩在线另类| 国产精品久久久久久久久久| 91色精品视频在线| 亚洲精品动漫久久久久| 国产亚洲美女精品久久久| 色妞在线综合亚洲欧美| 日韩精品中文字幕久久臀| 日韩欧中文字幕| 亚洲精品视频中文字幕| 国产精品精品久久久| 亚洲成人精品视频在线观看| 色阁综合伊人av| 久99久在线视频| 久久免费视频在线观看| 欧美激情综合色| 久久男人av资源网站| 成人免费在线视频网址| 欧美怡红院视频一区二区三区| 自拍亚洲一区欧美另类| 亚洲爱爱爱爱爱| 7m第一福利500精品视频| www.日本久久久久com.| 欧美性xxxxxxxxx| 国产精品www网站| 日本亚洲欧美三级| 久久精品视频在线| 欧美做受高潮电影o| 韩剧1988在线观看免费完整版| 国外成人在线视频| 欧美福利在线观看| 亚洲男人天堂古典| 国产精品免费在线免费| 国产精品网址在线| 亚洲精品日韩久久久| 国产精品视频xxxx| 久久久久久com| 精品性高朝久久久久久久| 欧美亚洲另类视频| 亚洲欧洲日产国产网站| 精品日韩美女的视频高清| 亚洲欧洲在线观看| 欧美精品一区二区三区国产精品| 高清一区二区三区四区五区| 欧美乱妇高清无乱码| 欧美精品福利在线| 欧洲成人在线视频| 成人亚洲欧美一区二区三区| 欧美日本在线视频中文字字幕| 在线观看精品自拍私拍| 欧美限制级电影在线观看| 精品一区二区三区电影| 亚洲18私人小影院| 日韩在线精品一区| 日韩动漫免费观看电视剧高清| 亚洲一区二区三区乱码aⅴ蜜桃女| 丝袜情趣国产精品| 日韩精品免费视频| 亚洲成人av片| 亚洲欧洲国产一区| 国产精品成人av在线| 欧美中文字幕在线播放| 亚洲黄页网在线观看| 色妞欧美日韩在线| 欧美激情精品久久久久久免费印度| 欧美一级视频在线观看| 午夜精品久久久久久久99黑人| 国产91成人在在线播放| 一区国产精品视频| 亚洲男人7777| 日韩欧美国产高清91| www日韩中文字幕在线看| 国产精品香蕉国产| 久久久中文字幕| 麻豆一区二区在线观看| 色噜噜狠狠色综合网图区| 国产伦精品一区二区三区精品视频| 日韩av片免费在线观看| 欧美麻豆久久久久久中文| 久久久久久久国产精品| 亚洲国产中文字幕久久网|