Assigning blame?

'allo

Say I have two classes:

class Bloke
  attr_reader :name
  def sellSoul(aDemon)
    aDemon.buySoul(self)
  end
end

class Demon
  def buySoul(aBloke)
    # if aBloke called the method, OK. Else, tell them where to go.
    puts("I bought #{aBloke.name}'s soul!")
  end
end

Tim = Bloke.new
Tim.name = "Tim"
Satan = Demon.new
Tim.sellSoul(Satan)

I would like the buySoul method to work only if the Bloke calling it is
the same instance of Bloke named, but I can't find any way to determine
what object called a given method. Does anyone have a suggestion?

Cheers

···

--
Ben

Ben Zealley wrote:

'allo

Say I have two classes:

class Bloke
  attr_reader :name
  def sellSoul(aDemon)
    aDemon.buySoul(self)
  end
end

class Demon
  def buySoul(aBloke)
    # if aBloke called the method, OK. Else, tell them where to go.
    puts("I bought #{aBloke.name}'s soul!")
  end
end

Tim = Bloke.new
Tim.name = "Tim"
Satan = Demon.new
Tim.sellSoul(Satan)

I would like the buySoul method to work only if the Bloke calling it is
the same instance of Bloke named, but I can't find any way to determine
what object called a given method. Does anyone have a suggestion?

Not quite what you're after, but it has the same effect: make sellSoul a private method, so that it's only possible (without #send contortions) for Tim to call sellSoul on self.

Other than that, I think you'll be into checking object_ids against constants at the top execution level, which isn't particularly useful. You could pass the binding to buySoul, I guess, but that's just as nasty.

···

--
Alex

Ben Zealley wrote:

'allo

Say I have two classes:

class Bloke
  attr_reader :name
  def sellSoul(aDemon)
    aDemon.buySoul(self)
  end
end

class Demon
  def buySoul(aBloke)
    # if aBloke called the method, OK. Else, tell them where to go.
    puts("I bought #{aBloke.name}'s soul!")
  end
end

Tim = Bloke.new
Tim.name = "Tim"
Satan = Demon.new
Tim.sellSoul(Satan)

I would like the buySoul method to work only if the Bloke calling it is
the same instance of Bloke named, but I can't find any way to determine
what object called a given method. Does anyone have a suggestion?

Some might argue that you can't do thi, b/c in reality what you want to
do is flawed conceptually. Be that as it may, you're essentially asking
for the Binding.of_caller, a well known extension, but one that is far
from perfect too. Albiet, in your case, and most cases I have ever
considered, a "self_of_caller" would suffice --the whole binding is
generally overkill. In any case, it can be done generally if you pass a
block:

  require 'facet/binding/self' # see below for this code

  class Bloke
   attr_reader :name
   def sellSoul(aDemon)
     aDemon.buySoul{self}
   end
end

class Demon
   def buySoul(&aBloke)
     # if aBloke called the method, OK. Else, tell them where to go.
                if aBloke.binding.self == Bloke
         puts("I bought #{aBloke.name}'s soul!")
                else
                  puts "You know were to go!"
                end
   end
end

T.

P.S. binding/self + binding/eval:

class Binding

  # Returns the self in the binding context.
  def self()
    @self ||= eval( "self" )
    @self
  end

  # Evaluate a Ruby source code string (or block) in the binding
context
  def eval( str ) #='', &blk )
     Kernel.eval( str, self )
  end

end

Some might argue that you can't do thi, b/c in reality what you want to
do is flawed conceptually.

Thankyou for the code - but would you explain to me why it's "flawed
conceptually"? I'm still relatively new to OO thinking - if it's
improper to have a way of identifying the object that called one of
your methods, I'd like to know why...

Cheers

···

--
Ben