2012-07-20 63 views
0

我,如果一個屬性進行訪問其屬性沒有數據,從一個REST API動態加載數據的模型:如何在RubyOnRails中實現魔術功能?

class Issue 
    attr_accessor :ticket_title, :priority, :description 
    @ticket_title 
    @priority 
    @description 

    def priority 
    if [email protected]? 
     updateProperties() 
    end 
    @priority 
    end 
    def description 
    if [email protected]? 
     updateProperties() 
    end 
    @description 
    end 
    def ticket_title 
    if [email protected]_title.empty? 
     updateProperties() 
    end 
    @ticket_title 
    end 

    def updateProperties 
    # loads all data from REST API 
    end 

    def initialize (hsh = {}) 
     hsh.each { |key, value| 
     self.instance_variable_set("@#{key}", value) 
     } 
    end 

end 

有兩個問題:

  1. 如果我初始化與模型RedmineIssue.new :ticket_title => 'test',我不希望模型打電話給updateProperties,但它不知道怎麼做。
  2. 有什麼辦法可以神奇地聲明函數嗎?也就是說,如果沒有真正的函數嘗試運行元函數?
+0

你是什麼意思,「神奇」? – 2012-07-20 16:52:10

+0

我試過'Issue.new:ticket_title =>'test'',它沒有調用'updateProperties'。還有別的東西你沒有顯示。 – 2012-07-20 16:53:47

+0

如果我通過「神奇地」理解你的意思,你需要'method_missing'鉤子。順便說一下,你的初始化可能非常不安全,而且效率不高。使用'instance_variable_set'替換一個散列。 – Linuxios 2012-07-20 16:58:08

回答

1

那麼,這裏是「魔法」的東西。在你的類,如果你希望能夠通過一個名爲get_whateverthekeyis方法來獲得哈希的任何部分(例如傻,我知道),你會使用method_missing

class Foo 
    def initialize 
    @h = {} 
    end 
    def method_missing(name, *args, &block) 
    if(name =~ /\Aget_(.+)\Z/) 
     #Name is valid 
     sig_class.class_exec($1) do |n| 
     define_method("get_"+n) {@h[n]} 
     end 

     @h[$1] 
    elsif(name =~ /\Aset_(.+)\Z/) 
     #Name is valid 
     sig_class.class_exec($1) do |n| 
     define_method("set_"+n) {|v| @h[n]=v} 
     end 

     @h[$1] = args[0] 
    else 
     super 
    end 
    end 
    private 
    def sig_class 
    class << self 
     self 
    end 
    end 
end 

當沒有定義的方法,它會去method_missing。當發生這種情況時,method_missing對散列進行請求的操作,然後動態地定義該方法,以便下一次它是直接方法調用,這意味着由於該方法已經存在而更有效。這與Ruby自己的OpenStruct使用的method_missing有些相似。

+0

嗨。感謝你和+1。我會在下週嘗試來源並在此之後標記答案。謝謝! – 2012-07-22 11:06:50

+0

@hijolan:當然。很高興我能幫上忙。 – Linuxios 2012-07-22 14:01:16

3

要動態添加方法,你應該閱讀關於method_missing
好文章解釋它的一些方面。
http://www.trottercashion.com/2011/02/08/rubys-define_method-method_missing-and-instance_eval.html

+0

這是解決問題的正確方法,但似乎在模型之外添加單例可能是解決問題核心的更好方法。 – supermoogle 2012-07-20 17:59:22

+0

謝謝你的回答。同時我也找到了method_missing鉤子......但是感謝你的友好鏈接和+1! Linuxios的答案有點更詳細,所以我先嚐試完整源代碼... – 2012-07-22 11:04:25