2010-04-24 2 views
16

Я надеюсь, что инфраструктура передачи сообщений Ruby означает, что для этого может быть какой-то умный трюк.Любой способ определить, какой объект называется методом?

Как определить вызывающий объект - какой объект называется методом, в котором я сейчас?

ответ

6

Как вариант, существует binding_of_caller gem, который позволяет выполнять код в контексте любого вызывающего абонента в стеке вызовов (вызывающего абонента, вызывающего абонента и т. Д.). Это полезно для проверки (см. делать что-либо в любой позиции в стеке вызовов) стек вызовов в разработке, как используется в better_errors.

Объекты класса Binding инкапсулируют контекст выполнения в определенном месте в коде и сохраняют этот контекст для использования в будущем.

http://www.ruby-doc.org/core-2.1.4/Binding.html

Должен ли я упомянуть, этот метод следует использовать только для отладки, развлечения или образовательных целей, поскольку это нарушает принципы объектно-ориентированного программирования на самом деле плохо.
Главным образом из-за 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 номер для получения привязки вызывающего абонента.

Ужасно хакеры. Но если вам действительно нужно это —, вы идете.

1

Вы имеете в виду, как self?

irb> class Object 
    .. def test 
    ..  self 
    .. end 
    .. end 
    => nil 
irb> o = Object.new 
    => #<Object:0xb76c5b6c> 
irb> o.test 
    => #<Object:0xb76c5b6c> 
+17

++ Чувак, это совершенно удивительным, как это выглядит как стилизованный Z – Pierreten

+0

Я прочитал вопрос, что внутри вашего 'test()' OP хочет получить объект, который вы получаете, если просто введите 'self' в irb. – lulalala

12

Вы можете легко найти в строке кода, который вызвал функцию интереса через

caller.first 

, который сообщит вам имя файла и номер строки, который назвал соответствующую функцию. Тогда вы могли бы спрогнозировать, какой именно объект.

Однако, похоже, что вы больше после некоторого объекта, который вызвал определенную функцию, возможно, в методе экземпляра. Я не знаю метода для выяснения этого - но я бы не использовал его в любом случае, поскольку он, похоже, плохо нарушает инкапсуляцию.

+1

Это действительно хороший момент, я просто передаю вызывающий объект Вместо этого идея заключалась в том, чтобы упростить некоторые из аргументов метода, автоматически отражая некоторую информацию о вызывающем объекте. –

+1

хорошо, в идеале, если это несколько раз, это должен быть метод в суперклассе, и вы можете использовать 'self '. – Peter

2

технологии на ее лучших:

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 сценария.

Посмотрите на phone.rb:13! Этот метод dial - это то, что послал звонок! И phone.rb:22 относится к безрассудному драйверу, который использовал метод dial!

1

Петра answer используется в примере производства кода

В моей компании мы протестующие deleted флаг в аромате Paranoia gemdeleted_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 
Смежные вопросы