Search code examples
rubyself

Trusting the object that was just returned?


Is there a practical application to the "crazy-ness" below?

It seems like this is a way for ted to always be able to return himself to the world and people will think they are talking to ted who they expect to act a certain way and be a certain age... but he isn't acting the way he portrays himself and is lying about his age to someone.

What 'trickery' is possible when an object is returned and you check on what that object represents and is capable of... but really that object was acting another way and capable of other things before returning.

class Person

  def age
    21
  end

  def who_am_i?
    puts "I am #{self} / #{object_id} and I am #{age} years old"
    self
  end
end


ted = Person.new

def ted.singleton_who_am_i?       

    class << self
      def age
        0
      end
    end

    puts "I am #{self} / #{object_id} and I am #{age} years old"
    self
end

puts ted.who_am_i? == ted.singleton_who_am_i?



>> I am #<Person:0x100138340> / 2148123040 and I am 21 years old
>> I am #<Person:0x100138340> / 2148123040 and I am 0 years old
>> true

Solution

  • http://andrzejonsoftware.blogspot.ca/2011/02/dci-and-rails.html

    in DCI, your data model gets different type of behavior based on the context it is used it. Usually it is done with object.extend, but it is pretty much what you are doing above -- taking advantage of the metaclass.

    Another example (and probably why things work that way) is the way classes work in ruby. If you say

    class Foo
    end
    

    that is the same thing as saying

    Foo = Class.new
    end
    

    meaning that what you are doing is assigning a new instance of class Class to a constant. When you define a method on that class, you don't want it applied to all instance of class Class, you only want it on the class you are defining. So when you say

    class Foo
      def self.bar
      end
    end
    

    it is the exact thing as saying

    class Foo
    end
    
    def Foo.bar
    end
    

    which is exactly the same principal as you are talking about in your question

    (sorry if that was unclear)