Nic Lin's Blog

喜歡在地上滾的工程師

神奇的 method missing

Rails裡面我們常調用到來自ActiveRecord::FinderMethods的find_by這個方法,但神奇的是如果我們在後面多加變成find_by_id or find_by_name之類的方式竟然都不會出錯,這個神奇方法的底層就來自於Ruby的method missing,只要在適當的時機覆寫他就可以達到以程式撰寫程式碼的效果也就是所謂Meta-programming。

假設我們不使用method missing,而使用define method,就要定義一些有可能根本用不到的方法,例如:

find_by_email
find_by_login
find_by_name
find_by_id
find_by_email_and_login
find_by_email_and_login_and_name
find_by_email_and_name
#....

那這時候權衡利弊最佳情況就是在適當時機覆寫method missing,因為Ruby在尋找方法時會先往該物件的類別做尋找,找不到再往父類別找,當都找不到時就會去call method missing。

以下舉個簡單例子

class Dog
  def sleeping
    puts "ZZZZZ~~"
  end

  def method_missing(method_name, *args)
    if method_name.to_s.start_with?("say")
      q = method_name.to_s.sub("say_", "")
      puts "say #{q}"
    end
  end
end

輸出結果:

d = Dog.new
puts d.sleeping # => ZZZZZ~~
puts d.say_haha # => say haha

參考文章: - method_missing,一个 Ruby 程序员的梦中情人 - Ruby也可以這樣寫 - Ruby Metaprogramming - Method Missing

comments powered by Disqus