Michael Cordell's Blog

Ruby Notes

16 Jul 2013

Objects

Classes

Instance Variables

Method calls

MyClass.ancestors
#This will fail:
class MyClass
  def test_private()
    self.tested()
  end

  private
    def tested
      puts "tested!"
    end
end

MyClass.new.test_private

#This will work:
class MyClass
    def test_private()
        tested()
    end

  private
    def tested
      puts "tested!"
    end
end

MyClass.new.test_private

Bindings

Bindings are essentially scopes without code. They are packaged scopes that you can be used with eval later on to evaluate code within a given context. Example:

class BinderTest
  def this_is_a_binding_method()
    @insider_variable = 4
    binding
  end
end

bound = BinderTest.new.this_is_a_binding_method()


eval "puts 2 + @insider_variable", bound
#=> 6

TOPLEVEL_BINDING allows you to access the top-level scope from anywhere.

Tainted Strings and Safe Levels

In Ruby, tainted strings are those that Ruby marks as coming from an external source (not clear on how it makes this designation). Calling tainted? will allow you to determine if an object is from or mixed with an external source. This helps when deciding on whether to use eval() on a string. Further, setting the ruby value $SAFE sets the safe level, which allows or disallows certain operations. The range is 0..4 and anything other than 0 disallows evaluating tainted strings.

Singleton Methods

Singleton methods are those which are defined on a single object:

  class TestSingle
  end

  object = TestSingle.new
  def object.singleton_method
    puts "method on a single object"
  end

  object.singleton_method #=> "method on a single object"
  TestSingle.respond_to? :singleton_method #=> false

Class methods are a type of singleton object. When defining a class method, you are actual using a self to refrence the Class object you are working on.

class ClassMethods

  def self.this_is_a_class_method
    "class method"
  end

end

def ClassMethod.this_is_another_class_method
  "defined similar to a more singleton looking way"
end

Ghost Method

class GhostMethod
  def method_missing(name, *args)
    puts name.capitalize
  end
end

Pattern Dispatch

Call methods based on their name

#Call methods in object that start with "test"
object.methods.each do |method|
  object.send(method) if method.to_s =~ /^test/
end

Dynamic Method

Dynamically create methods at runtime

class Empty
end

Empty.class_eval do
  define_method :method_name do
    puts "This method was defined at runtime"
  end
end

object = Empty.new
object.method_name # => "This method was defined at runtime"

Dynamic Proxy

Dynamic Proxies (e.g. ActiveRecord) forwards ghost method calls to another object (e.g. a database). Be mindful of:

class DP
  def initialize(database)
    @database = database
  end

  def method_missing(name, *args)
    super if !@database.respond_to?("get_#{name}")
    info = @database.send("get_#{name}")
  end
end

Blank slate

remove methods from Object to prevent method name collisions

class BlankSlate
  instance_methods.each do |m|
    undef_method m unless m.to_s /^method_missing$|^respond_to\?$|^__/
  end
end