有办法确定哪个对象叫做方法吗?

时间:2022-10-30 00:09:01

I'm hoping that Ruby's message-passing infrastructure means there might be some clever trick for this.

我希望Ruby的消息传递基础设施意味着可能会有一些巧妙的技巧。

How do I determine the calling object -- which object called the method I'm currently in?

如何确定调用对象——调用当前方法的对象?

5 个解决方案

#1


6  

As an option, there is a binding_of_caller gem that allows you to execute code in context of any caller on the call stack (caller, caller's caller and so on). It's useful for inspecting (read do anything at any position on the call stack) call stack in development, as used in better_errors.

作为一个选项,binding_of_caller gem允许您在调用堆栈上的任何调用者(调用者、调用者的调用者等)的上下文中执行代码。它对于在开发中检查(在调用堆栈上的任何位置执行任何操作)调用堆栈非常有用,就像在better_errors中使用的那样。

Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use.

类绑定的对象将执行上下文封装在代码中的某个特定位置,并保留此上下文供将来使用。

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

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

Should I mention, this technique should only be used for debugging, fun or educational purposes, because it violates principles of OOP really badly.
Mostly because of eval.

应该说,这种技术应该只用于调试、娱乐或教育目的,因为它严重违反了OOP的原则。主要是因为eval。

Let's prepare stuff:

让我们准备的东西:

require 'binding_of_caller' # I assume, you installed this gem already?

Get the immediate (closest on stack, hence 0) caller instance:

获取即时(最接近堆栈,因此0)调用者实例:

binding.of_caller(0).eval('self')

...or even an immediate calling method:

…甚至是即时调用方法:

binding.of_caller(0).eval('__method__')

If you need to get higher up the call stack, use numbers other than 0 for getting a caller's binding.

如果您需要在调用堆栈上获得更高的值,请使用非0的数字来获取调用者的绑定。

Awfully hacky. But if you really need this — there you go.

是出租汽车司机。但如果你真的需要这个,那就去吧。

#2


12  

You can easily look at the line of code that called the function of interest through

您可以轻松地查看调用所感兴趣的函数的代码行

caller.first

which will tell you the filename and line number which called the relevant function. You could then back-calculate which object it was.

它将告诉您文件名和行号,并调用相关函数。然后你可以算出它是哪个对象。

However, it sounds like you're more after some object that called a certain function, perhaps within an instance method. I'm not aware of a method for figuring this out - but I wouldn't use it anyway, since it seems to violate encapsulation badly.

但是,听起来好像您是在一个被称为某个函数的对象之后,也许是在一个实例方法中。我不知道有什么方法可以解决这个问题——但我也不会使用它,因为它似乎严重违反了封装。

#3


2  

Technology at its finest:

技术最好的:

 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>'"]

Note: Line number for demonstrative purposes. phone.rb:X refers to Line X of the script.

注:用于演示目的的行号。电话。rb:X是指脚本的X行。

Look at phone.rb:13! This dial method is what sent the call! And phone.rb:22 refers to the reckless driver that used the dial method!

看看phone.rb:13 !这个拨号方式就是发送呼叫的方式!和电话。rb:22是指使用拨号方式的鲁莽驾驶!

#4


1  

You mean like self?

你的意思是喜欢自己吗?

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

#5


1  

Peter's answer used in production code example

在生产代码示例中使用了Peter的答案。

In my company we were deprecating deleted flag in flavor of Paranoia gem deleted_at column. The code bellow is how we were ensuring all will go well before we remove column (deploying this code and then after 2 or 3 days of being live we deploy migration remoove_column :lessons, :deleted

在我的公司里,我们在专栏中删除了带有gem deleted_at味道的被删除的标志。代码bellow是我们在删除列之前确保一切顺利的方法(部署这个代码,然后在2或3天的live之后,我们部署了迁移remoove_column:教训,:删除。

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

#1


6  

As an option, there is a binding_of_caller gem that allows you to execute code in context of any caller on the call stack (caller, caller's caller and so on). It's useful for inspecting (read do anything at any position on the call stack) call stack in development, as used in better_errors.

作为一个选项,binding_of_caller gem允许您在调用堆栈上的任何调用者(调用者、调用者的调用者等)的上下文中执行代码。它对于在开发中检查(在调用堆栈上的任何位置执行任何操作)调用堆栈非常有用,就像在better_errors中使用的那样。

Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use.

类绑定的对象将执行上下文封装在代码中的某个特定位置,并保留此上下文供将来使用。

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

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

Should I mention, this technique should only be used for debugging, fun or educational purposes, because it violates principles of OOP really badly.
Mostly because of eval.

应该说,这种技术应该只用于调试、娱乐或教育目的,因为它严重违反了OOP的原则。主要是因为eval。

Let's prepare stuff:

让我们准备的东西:

require 'binding_of_caller' # I assume, you installed this gem already?

Get the immediate (closest on stack, hence 0) caller instance:

获取即时(最接近堆栈,因此0)调用者实例:

binding.of_caller(0).eval('self')

...or even an immediate calling method:

…甚至是即时调用方法:

binding.of_caller(0).eval('__method__')

If you need to get higher up the call stack, use numbers other than 0 for getting a caller's binding.

如果您需要在调用堆栈上获得更高的值,请使用非0的数字来获取调用者的绑定。

Awfully hacky. But if you really need this — there you go.

是出租汽车司机。但如果你真的需要这个,那就去吧。

#2


12  

You can easily look at the line of code that called the function of interest through

您可以轻松地查看调用所感兴趣的函数的代码行

caller.first

which will tell you the filename and line number which called the relevant function. You could then back-calculate which object it was.

它将告诉您文件名和行号,并调用相关函数。然后你可以算出它是哪个对象。

However, it sounds like you're more after some object that called a certain function, perhaps within an instance method. I'm not aware of a method for figuring this out - but I wouldn't use it anyway, since it seems to violate encapsulation badly.

但是,听起来好像您是在一个被称为某个函数的对象之后,也许是在一个实例方法中。我不知道有什么方法可以解决这个问题——但我也不会使用它,因为它似乎严重违反了封装。

#3


2  

Technology at its finest:

技术最好的:

 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>'"]

Note: Line number for demonstrative purposes. phone.rb:X refers to Line X of the script.

注:用于演示目的的行号。电话。rb:X是指脚本的X行。

Look at phone.rb:13! This dial method is what sent the call! And phone.rb:22 refers to the reckless driver that used the dial method!

看看phone.rb:13 !这个拨号方式就是发送呼叫的方式!和电话。rb:22是指使用拨号方式的鲁莽驾驶!

#4


1  

You mean like self?

你的意思是喜欢自己吗?

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

#5


1  

Peter's answer used in production code example

在生产代码示例中使用了Peter的答案。

In my company we were deprecating deleted flag in flavor of Paranoia gem deleted_at column. The code bellow is how we were ensuring all will go well before we remove column (deploying this code and then after 2 or 3 days of being live we deploy migration remoove_column :lessons, :deleted

在我的公司里,我们在专栏中删除了带有gem deleted_at味道的被删除的标志。代码bellow是我们在删除列之前确保一切顺利的方法(部署这个代码,然后在2或3天的live之后,我们部署了迁移remoove_column:教训,:删除。

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