Class: Object

Inherits:
BasicObject
Defined in:
lib/qualitysmith_extensions/object/mcall.rb,
lib/qualitysmith_extensions/object/default.rb,
lib/qualitysmith_extensions/object/methods.rb,
lib/qualitysmith_extensions/object/send_if.rb,
lib/qualitysmith_extensions/object/ignore_access.rb,
lib/qualitysmith_extensions/object/singleton_send.rb,
lib/qualitysmith_extensions/object/send_if_not_nil.rb

Overview

Author

Tyler Rick

Copyright

Copyright © 2007 QualitySmith, Inc.

License

Ruby License

Submit to Facets?

Maybe.

Developer notes

++

Instance Method Summary collapse

Instance Method Details

#default!(default_value) ⇒ Object



31
32
33
# File 'lib/qualitysmith_extensions/object/default.rb', line 31

def default!(default_value)
  # This should have no effect on any objects other than instances of NilClass.
end

#ignore_accessObject Also known as: access

Sends all messages to receiver, bypassing access restrictions, allowing you to call private methods (like class_variable_get) without having to write ugly send() calls.

o.class.ignore_access.class_variable_set(:@@v, 'new value')

is equivalent to:

o.class.send(:class_variable_set, :@@v, 'new value')

If you tried to just call the method directly, like this:

o.class.class_variable_set(:@@v, 'new value')

you would get a NoMethodError:

NoMethodError: private method `class_variable_set' called for Klass:Class


36
37
38
39
40
# File 'lib/qualitysmith_extensions/object/ignore_access.rb', line 36

def ignore_access
  @_ignore_access_functor ||= Functor.new do |op,*args|
    self.send(op,*args)
  end
end

#mcall(moduule, message, *args, &block) ⇒ Object Also known as: msend

Calls the method implementation from the module of your choice (moduule) on the object of your choice (self).

The only (huge) catch is that self must either be an instance of moduule or have moduule as an ancestor… which severely limits its usefullness. (Compare with singleton_send.)

It is still useful, though, if you want to call some “original” implementation provided by Kernel (or some other base module) and the people that overrode it didn’t play nice and use alias_method_chain.

No matter! If the class of the object you are calling this on has Kernel as an ancestor, then you can call any method from Kernel on this object!

This implementation is gratefully owed to the folks who wrote PP (/usr/lib/ruby/1.8/pp.rb)



19
20
21
# File 'lib/qualitysmith_extensions/object/mcall.rb', line 19

def mcall(moduule, message, *args, &block)
  moduule.instance_method(message).bind(self).call(*args, &block)
end

#methods_with_sorting_and_include_super(include_super = true) ⇒ Object

Adds the following features to the built-in Object#methods:

  • Provides the same include_super option that Module#instance_methods has (Backwards compatible, because default is true)

  • Returns an array of symbols rather than strings (Not backwards compatible)

  • Sorts the array for you so you don’t have to! (Not backwards compatible)



19
20
21
22
23
24
25
# File 'lib/qualitysmith_extensions/object/methods.rb', line 19

def methods_with_sorting_and_include_super(include_super = true)
  if include_super
    methods_without_sorting_and_include_super
  else
    (methods_without_sorting_and_include_super - Object.methods_without_sorting_and_include_super)
  end.sort.map(&:to_sym)
end

#send_if(condition, message, *args, &block_to_always_execute) ⇒ Object

But only sends message to self if condition is met.

If a block (block_to_always_execute) is supplied, it is passed on to the message if the condition is met; (otherwise it is simply called without sending the message).

This is useful if you want to wrap a block with some method but you only want the method itself to be used some of the time. For example, if it’s for benchmarking, you may only want to enable it during development but disable during production to save on some overhead.

Note: this cannot be used to call methods that expect blocks (Ruby 1.9 maybe?)



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/qualitysmith_extensions/object/send_if.rb', line 31

def send_if(condition, message, *args, &block_to_always_execute)
    if condition
      self.__send__(message, *args, &block_to_always_execute)
    else
      if block_given?
        block_to_always_execute.call
      else
        self
      end
    end
end

#send_if_not_nil(message, *args) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/qualitysmith_extensions/object/send_if_not_nil.rb', line 10

def send_if_not_nil(message, *args)
  if message
    send(message, *args) 
  else
    self
  end
end

#send_if_true(condition, *args, &block) ⇒ Object

Lets you reduce duplication a little bit. Can do this:

@foo.send_if_true(color)

instead of this:

@foo.send_if(color, color)


53
54
55
# File 'lib/qualitysmith_extensions/object/send_if.rb', line 53

def send_if_true(condition, *args, &block)
  self.send_if(condition, condition, *args, &block)
end

#send_unless(condition, *args, &block) ⇒ Object

Opposite of send_if



44
45
46
# File 'lib/qualitysmith_extensions/object/send_if.rb', line 44

def send_unless(condition, *args, &block)
  self.send_if(!condition, *args, &block)
end

#singleton_send(moduule, message, *args, &block) ⇒ Object Also known as: ss

Creates a singleton method and then calls it.

More specificaly, it extends self with the methods from moduule and then sends the supplied message and args (if any).

Examples:

"whatever".ss(MyColorizer, :colorize, :blue)

Advantages:

  • Keeps things object-oriented. Better than having global/class methods.

    • ("whatever".ss(MyColorizer, :colorize).ss(SomeOtherClass, :another_class_method) instead of

      • SomeOtherClass::another_class_method(MyColorizer::colorize("whatever")))

    • Method calls are listed in the order in which they are called.

  • Still lets you keep your methods in a namespace.

  • Doesn’t clutter up the base classes with methods that are only useful within a very small context. The methods are only added to the objects you specify. So you can “use” the base class without cluttering up all instances of the class with your methods.

  • Useful for cases where creating a subclass wouldn’t help because the methods you are calling would still return instances of the base class.

Disadvantages:

  • You have to have/create a module for the functions you want to use.

    • Can’t just call .sigleton_send(self, :some_method) if you want to use some_method that’s defined in self.

    • So what do we call the module containing the “singleton method”? String::MyColorizer? MyColorizer::String? MyStringColorizer?

Adding methods to the base class using Facets’ own namespacing facilities (Module#namespace and Module#include_as) might actually be a more sensible alternative a lot of the time than bothering to create singleton methods for single objects! That would look somethig like:

class String
  namespace :my_colorizer do
    def colorize(...); ...; end
  end
end
"whatever".my_colorizer.colorize(:blue)

or

class String
  include_as :my_colorizer => MyColorizer
end
"whatever".my_colorizer.colorize(:blue)


61
62
63
64
# File 'lib/qualitysmith_extensions/object/singleton_send.rb', line 61

def singleton_send(moduule, message, *args, &block)
  self.extend(moduule)
  self.send(message, *args, &block)
end