以前你可能讀到Ruby元編程,也許你的一些項目中使用它,但一些最流行的開源項目是如何利用這個特性?git
答案在這篇文章中!github
Rails大量使用元編程,這是一個開始的好地方。編程
例如,當您想要檢查當前環境,在你的Rails應用程序,你作些什麼:ruby
Rails.env.production?
但什麼是 env而且這是如何工做的呢?答案是 StringInquirer類,String這個類的一個子類。這個類使用 method_missing,讓你能夠調用 env.production?而不是 env == production.post
代碼是這樣的:學習
def method_missing(method_name, *arguments) if method_name[-1] == '?' self == method_name[0..-2] else super end end
這就是說:「若是是以問號結尾的方法名稱就作比較,不然繼續祖先鏈」。網站
原始代碼可在這裏找到.ui
若是您之前使用過Sinatra你可能知道有兩種方法來定義你的路由:經過使用 get / post這種獨立於任何類之外的直接方法,或經過定義一個類繼承自 Sinatra::Application.this
Sinatra的DSL(領域特定語言)方法定義在 Sinatra::Application內,因此你如何在這個類之外使用呢?code
嗯,這裏有兩個事情:元編程和模塊的擴展。
Sinatra定義了一個 Sinatra::Delegator模塊,在base.rb,用於將方法調用委託給一個 target。默認狀況下目標設置爲 Sinatra::Application。
這是一個簡化版的定義於Sinatra::Delegator的delegate類方法:
def self.delegate(*methods) methods.each do |method_name| define_method(method_name) do |*args, &block| Delegator.target.send(method_name, *args, &block) end end end delegate :get, :patch, :put, :post, :delete
這段代碼建立了一組方法( define_method),將傳遞方法調用到 Sinatra::Application(Delegator.target的默認值).
而後 main對象被擴展,使用 Sinatra::Delegator定義的方法,這使得Sinatra的DSL可用 Sinatra::Application類。
值得注意的是,Ruby有兩個用於方法委託的內置類,若是你須要他們:Delegator & Forwardable.
Paperclip是gem,幫助您的應用程序來處理文件上傳。文件加在ActiveRecord模型。has_attached_file方法定義附加文件。
例如:
class User has_attached_file :avatar, :styles => { :normal => "100x100#" } end
該方法定義在paperclip.rb,它使用元編程在模型定義方法。該方法可用於訪問文件附件(Paperclip::Attachment類的一個實例)。例如,若是附加文件 :avatar, Paperclip將定義一個 avatar方法在模型上。
這是 define_instance_getter方法負責:
# @name => The name of the attachment # @klass => The ActiveRecord model where this method is being defined def define_instance_getter name = @name options = @options @klass.send :define_method, @name do |*args| ivar = "@attachment_#{name}" attachment = instance_variable_get(ivar) if attachment.nil? attachment = Attachment.new(name, self, options) instance_variable_set(ivar, attachment) end end end
從這段代碼中咱們能夠看到,對象存儲在附件 @attachment_#{name}實例變量。在咱們的例子中 @attachment_avatar.
而後檢查這個附件已經存在,若是它不存在,它建立一個新的 Attachment對象和設置實例變量。
這是原始源代碼.
如您所見,元編程是一個很是強大和靈活的技術,但當你想要使用的時候請記得這句話:「強大意味着更大的責任」。
若是你喜歡這篇文章,不要忘了訂閱個人時事通信:)
廣告時間:
Ruby是知識海洋的貝殼,一塊兒來撿吧。
高性價比培訓:
一個月短時間培訓,自由學習無壓力
Rails網站開發入門,費用499
Ruby和Rails課程,能夠爲進入編程領域作準備
歡迎瞭解和交流