2010-05-25 85 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