Module: CrossCase

Included in:
Foo
Defined in:
lib/carat/crosscase.rb

Overview

A mixin which causes aliases for methods with either under_barred or camelCased naming conventions to be created in the opposing convention. E.g., in a class which mixes in CrossCase, defining a method which is called foo_bar will also create an alias for that method called fooBar.

Constant Summary collapse

Version =

Versioning constants

/([\d\.]+)/.match( %q{$Revision: 1.2 $} )[1]
Rcsid =
%q$Id: crosscase.rb,v 1.2 2003/07/25 17:00:24 deveiant Exp $

Class Method Summary collapse

Class Method Details

.extend_object(mod) ⇒ Object

Object-extension callback – installs aliases for any currently-extant class or instance methods, and installs callbacks that will create aliases for any subsequently-defined methods. Raises an error if any object except a Class or Module is extended.

Raises:

  • (TypeError)


113
114
115
116
117
118
119
120
121
# File 'lib/carat/crosscase.rb', line 113

def self::extend_object( mod )
    raise TypeError, "Expected a Module or a Class, got a " +
        mod.class.name unless
        mod.is_a?( Module )

    self::transformClassMethods( mod )
    self::transformInstanceMethods( mod )
    self::installMethodHooks( mod )
end

.findTargetMethods(*methodList) ⇒ Object

Find methods in the given methodList which are candidates for aliasing.



202
203
204
205
206
207
208
# File 'lib/carat/crosscase.rb', line 202

def self::findTargetMethods( *methodList )
  methodList.flatten.each {|meth|
    next if /(singleton_)?method_added/ =~ meth
    transformedName = transform( meth ) or next
    yield( meth, transformedName )
  }
end

.included(mod) ⇒ Object

The inclusion callback – uses the Ouroboros trick to extend including classes.



104
105
106
# File 'lib/carat/crosscase.rb', line 104

def self::included( mod )
    mod.extend( self )
end

.installAlias(mod, meth, aliasName) ⇒ Object

Install an alias aliasName for the given instance method meth of the Class or Module mod.



193
194
195
196
197
# File 'lib/carat/crosscase.rb', line 193

def self::installAlias( mod, meth, aliasName )
  unless mod.instance_methods(true).include?( aliasName )
    mod.module_eval %{alias_method :#{aliasName}, :#{meth}}
  end
end

.installClassAlias(mod, meth, aliasName) ⇒ Object

Install an alias aliasName for the given class method meth of the Class or Module mod.



172
173
174
175
176
177
178
179
# File 'lib/carat/crosscase.rb', line 172

def self::installClassAlias( mod, meth, aliasName )
  unless mod.respond_to?( aliasName )
    code = %{
      class << self; alias_method( :#{aliasName}, :#{meth} ); end
    }
    mod.module_eval( code, __FILE__, __LINE__ )
  end
end

.installMethodHooks(mod) ⇒ Object

Install method_added and singleton_method_added hooks into the given Module mod which auto-generate aliases for new methods.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/carat/crosscase.rb', line 126

def self::installMethodHooks( mod )
  mod.module_eval {
    class << self
      if respond_to?( :singleton_method_added )
        alias :__cc_sma :singleton_method_added
      end
      def singleton_method_added( id )
        if aliasName = CrossCase::transform( id )
          CrossCase::installClassAlias( self, id, aliasName )
        end
        if respond_to?( :__cc_sma )
          __cc_sma( id )
        else
          super
        end
      end

      if respond_to?( :method_added )
        alias :__cc_ma :method_added
      end                    
      def method_added( id )
        if aliasName = CrossCase::transform( id )
            CrossCase::installAlias( self, id, aliasName )
        end
        if respond_to?( :__cc_ma )
            __cc_ma( id )
        else
            super
        end
      end
    end
  }
end

.transform(mid) ⇒ Object

Return an alternate name for the given method id mid. If the method id is an under_barred method, returns a camelCased version, and vice-versa. If no alternate is called for, returns nil.



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/carat/crosscase.rb', line 214

def self::transform( mid )
  methodName = mid.to_s
  transformedName = ''

  # camelCased methods
  if /[A-Z]/.match( methodName ) && !/_/.match( methodName )
    transformedName = methodName.gsub( /([a-z0-9])([A-Z])/ ) {|match|
        $1 + '_' + $2
    }.downcase
      
  # underbarred_methods
  elsif !/A-Z/.match( methodName ) && /[a-z0-9]_[a-z]/.match( methodName )
    transformedName = methodName.gsub( /([a-z0-9])_([a-z])/ ) {|match|
        $1 + $2.upcase
    }

  else
    transformedName = nil
  end
  
  return transformedName
end

.transformClassMethods(mod) ⇒ Object

Search for and install aliases for either underbarred or camelCased class methods for mod (a Class or Module).



163
164
165
166
167
# File 'lib/carat/crosscase.rb', line 163

def self::transformClassMethods( mod )
  self::findTargetMethods( mod.singleton_methods(false) ) {|meth, aliasName|
      self::installClassAlias( mod, meth, aliasName )
  }
end

.transformInstanceMethods(mod) ⇒ Object

Search for and install aliases for either underbarred or camelCased instance methods for mod (a Class or Module).



184
185
186
187
188
# File 'lib/carat/crosscase.rb', line 184

def self::transformInstanceMethods( mod )
  self::findTargetMethods( mod.instance_methods(false) ) {|meth, aliasName|
    self::installAlias( mod, meth, aliasName )
  }
end