Я надеюсь, что инфраструктура передачи сообщений Ruby означает, что для этого может быть какой-то умный трюк.
Как определить вызывающий объект - какой объект называется методом, в котором я сейчас?
Я надеюсь, что инфраструктура передачи сообщений Ruby означает, что для этого может быть какой-то умный трюк.
Как определить вызывающий объект - какой объект называется методом, в котором я сейчас?
В качестве опции существует binding_of_caller
gem, который позволяет выполнять код в контексте любого вызывающего абонента в стеке вызовов (вызывающий, вызывающий абонент и т.д.). Это полезно для того, чтобы в процессе разработки (см. "Сделать что-нибудь в любой позиции в стеке вызовов" ), как используется в better_errors
.
Объекты класса
Binding
инкапсулируют контекст выполнения в определенном месте в коде и сохраняют этот контекст для будущего использования.
Следует ли упомянуть, что этот метод должен использоваться только для отладки, развлечений или образовательных целей, потому что он сильно нарушает принципы ООП.
В основном из-за eval
.
Пусть готовят материал:
require 'binding_of_caller' # I assume, you installed this gem already?
Получите
немедленный (ближайший к стеку, следовательно0
) экземпляр вызывающего:
binding.of_caller(0).eval('self')
... или даже метод немедленного вызова:
binding.of_caller(0).eval('__method__')
Если вам нужно подняться выше стека вызовов, используйте номера, отличные от 0
для получения привязки звонящего.
Ужасно хаки. Но если вам действительно нужно это? там вы идете.
Вы можете легко просмотреть строку кода, которая вызвала интересующую функцию через
caller.first
который укажет вам имя файла и номер строки, который называется соответствующей функцией. Вы могли бы затем запрограммировать, какой именно объект.
Однако, похоже, вы больше после некоторого объекта, который вызывает определенную функцию, возможно, в методе экземпляра. Я не знаю метода для выяснения этого - но я бы не использовал его в любом случае, поскольку он, похоже, плохо нарушает инкапсуляцию.
Технология в лучшем виде:
1 # phone.rb
2 class Phone
3 def caller_id
4 caller
5 end
6 end
7
8 class RecklessDriver
9 def initialize
10 @phone = Phone.new
11 end
12 def dial
13 @phone.caller_id
14 end
15 end
16
17 p = Phone.new
18 p.caller_id.inspect # => ["phone.rb:18:in `<main>'"]
19
20 macek = RecklessDriver.new
22 macek.dial.inspect # => ["phone.rb:13:in `dial'", "phone.rb:22:in `<main>'"]
Примечание: Номер строки для демонстрационных целей. phone.rb:X
относится к строке X
script.
Посмотрите phone.rb:13
! Этот метод dial
- это то, что послал вызов! И phone.rb:22
относится к безрассудному драйверу, который использовал метод dial
!
Вы имеете в виду как self
?
irb> class Object
.. def test
.. self
.. end
.. end
=> nil
irb> o = Object.new
=> #<Object:0xb76c5b6c>
irb> o.test
=> #<Object:0xb76c5b6c>
Peter ответ, используемый в примере производственного кода
В моей компании мы осуждали флаг deleted
в аромате Paranoia gem deleted_at
. Ниже приведен код, как мы гарантируем, что все будет хорошо, прежде чем мы удалим столбец (развертывание этого кода, а затем через 2 или 3 дня жизни мы развертываем миграцию remoove_column :lessons, :deleted
class Lesson < ActiveRecord::Base
def deleted
if caller.select { |c| c.match /serialization\.rb/ }.any?
# this is Rails object mapping
!!deleted_at
else
raise 'deplicated - deleted was replaced by deleted_at'
end
end
end