2010-05-25 65 views
0

基本上我不知道如何將在Ruby對象回調,這樣,當一個對象,無論如何變化,我可以自動觸發其他變化:紅寶石:在「ATTR」有回調對象

(編輯:我因爲@proxy是一個URI對象,它擁有它自己的方法,通過使用它自己的方法來改變URI對象並不會調用我自己的方法並更新@http對象)

class MyClass 
    attr_reader :proxy 
    def proxy=(string_proxy = "") 
    begin 
     @proxy = URI.parse("http://"+((string_proxy.empty?) ? ENV['HTTP_PROXY'] : string_proxy)) 
     @http = Net::HTTP::Proxy.new(@proxy.host,@proxy.port) 
    rescue 
     @http = Net::HTTP 
    end 
    end 
end 

m = MyClass.new 
m.proxy = "myproxy.com:8080" 
p m.proxy 
# => <URI: @host="myproxy.com" @port=8080> 

m.proxy.host = 'otherproxy.com' 
p m.proxy 
# => <URI: @host="otherproxy.com" @port=8080> 
# But accessing a website with @http.get('http://google.com') will still travel through myproxy.com as the @http object hasn't been changed when m.proxy.host was. 
+2

你是什麼意思「作爲代理=不被稱爲」?當然,它被稱爲。 – sepp2k 2010-05-25 15:00:11

+0

我不明白,你會得到'Net :: HTTP' ...?如果添加'attr_reader:http'並檢查'p m.http',可以檢查它。當'm.proxy'改變時,'proxy ='不會被調用嗎?該函數調用是唯一發生的事情 - 您不能直接在Ruby中更改實例變量。 – Amadan 2010-05-25 15:02:14

+0

啊褲子,我在我的例子中迷惑了自己!如果@proxy URI對象的子對象發生更改(請參閱我的示例代碼的最後4行),則不會調用'proxy ='方法 - 希望這更有意義嗎? – 2010-05-26 08:48:03

回答

0

我設法爲自己找出這一個!

# Unobtrusive modifications to the Class class. 
class Class 
    # Pass a block to attr_reader and the block will be evaluated in the context of the class instance before 
    # the instance variable is returned. 
    def attr_reader(*params,&block) 
    if block_given? 
     params.each do |sym| 
     # Create the reader method 
     define_method(sym) do 
      # Force the block to execute before we… 
     self.instance_eval(&block) 
      # … return the instance variable 
      self.instance_variable_get("@#{sym}") 
     end 
     end 
    else # Keep the original function of attr_reader 
     params.each do |sym| 
     attr sym 
     end 
    end 
    end 
end 

如果你的地方添加代碼,它會延長attr_reader方法,這樣,如果你現在做到以下幾點:

attr_reader :special_attr { p "This happens before I give you @special_attr" } 

它給你的@special_attr之前,它會觸發塊。它在實例範圍內執行,以便您可以使用它,例如,在從Internet下載屬性的類中。如果你這樣定義get_details其完成所有檢索和設置@details_retrievedtrue的方法,那麼你可以這樣定義ATTR:

attr_reader :name, :address, :blah { get_details if @details_retrieved.nil? } 
0

你行m.proxy = nil將引發NoMethodError例外,因爲nil確實沒有到0響應。因此,@http設置爲Net::HTTP,如在救援條款中。

這與回調/ setters無關。您應該修改您的代碼以執行您想要的操作(例如,如果使用有效支持,請致電string_proxy.blank?)。

+0

對不起,我設法混淆了自己,並提出錯誤的問題(我簡化了我的代碼,將它帶到了stackoverflow) - 謝謝你的幫助! – 2010-05-26 08:53:34