Created
November 3, 2011 08:15
-
-
Save jorgenpt/1336025 to your computer and use it in GitHub Desktop.
Objective-C-esque calling convention in Ruby (or: Why I shouldn't be let near method_missing)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See the bottom of the file for how this actually works. | |
module ObjC | |
def method_missing(method, *args) | |
ObjCCall.new(self, [], []).send(method, *args) | |
end | |
end | |
class ObjCCall | |
def initialize(obj, selector, args) | |
@obj = obj | |
@selector = selector | |
@args = args | |
end | |
def method_missing(method_sym, *args) | |
# This is for a more authentic Objective C experience. | |
#if @args.length > @selector.length | |
# raise ArgumentError, "You can only specify multiple arguments if it's the end of the method." | |
#end | |
method = method_sym.to_s | |
should_call = false | |
if method.end_with?('!') | |
method = method[0...-1] | |
should_call = true | |
end | |
ret = self.class.new(@obj, @selector + [method], @args + args) | |
ret = ret._send_call if should_call | |
ret | |
end | |
def _selector | |
@selector.join('_').to_sym | |
end | |
def _valid_call | |
@obj.respond_to?(_selector) | |
end | |
def +@; _send_call; end | |
def _send_call | |
if _valid_call | |
@obj.send(_selector, *@args) | |
else | |
raise NoMethodError, "undefined method `#{_selector}' for #{@obj.inspect}:#{@obj.class}" | |
end | |
end | |
end | |
if $0 == __FILE__ | |
class Test | |
include ObjC | |
def do_thing_with_other_thing(thing1, thing2) | |
[thing1, thing2] | |
end | |
end | |
test = Test.new | |
puts "ObjC Call!" | |
puts (+test.do_thing('laugh').with_other_thing('face')).inspect | |
puts | |
puts "Alternate ObjC Call!" | |
puts test.do_thing('laugh').with_other_thing!('face').inspect | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See the bottom of the file for how this actually works. | |
require 'objc_calling' | |
module ObjCMagic | |
def method_missing(m, *args) | |
ObjCCallMagic.new(self, [], []).send(m, *args) | |
end | |
end | |
class ObjCCallMagic < ObjCCall | |
def method_missing(m, *args) | |
ret = super | |
if ret.kind_of?(ObjCCall) and @obj.respond_to?(ret._selector) | |
ret._send_call | |
else | |
ret | |
end | |
end | |
end | |
if $0 == __FILE__ | |
class TestMagic | |
include ObjCMagic | |
def some_thing_with_other_thing(thing1, thing2) | |
[thing1, thing2] | |
end | |
end | |
puts "ObjC Call, Magic Edition!" | |
puts TestMagic.new.some_thing(1).with_other_thing(2).inspect | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is why we can't have nice things!