Ruby: обратные вызовы для объектов attr - PullRequest
0 голосов
/ 25 мая 2010

По существу, мне интересно, как разместить обратные вызовы для объектов в ruby, чтобы при любом изменении объекта я мог автоматически запускать другие изменения:

(РЕДАКТИРОВАТЬ: я запутался в своем собственном примере!Плохой знак… Поскольку @proxy является объектом URI, у него есть свои собственные методы, изменение объекта URI с помощью его собственных методов не вызывает мой собственный метод proxy= и не обновляет объект @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 ]

0 голосов
/ 15 июля 2010

Мне удалось выяснить это для себя!

# 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. Он выполняется в области действия экземпляра, поэтому вы можете использовать его, например, в классах, где атрибуты загружаются из Интернета. Если вы определяете метод, такой как get_details, который выполняет весь поиск и устанавливает @details_retrieved в true, тогда вы можете определить attr следующим образом:

attr_reader :name, :address, :blah { get_details if @details_retrieved.nil? }
0 голосов
/ 25 мая 2010

Ваша строка m.proxy = nil вызовет исключение NoMethodError, поскольку nil не отвечает на empty?. Таким образом, @http устанавливается на Net::HTTP, как в предложении спасения.

Это не имеет ничего общего с обратными вызовами / установщиками. Вы должны изменить свой код так, чтобы он делал то, что вы хотите (например, вызывать string_proxy.blank?, если используете activesupport).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...