Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allow the definition of instance and class methods with a block.

  • Loading branch information...
commit 38a1370ad83415fc9fbded1d1531dc0ca608b6f2 1 parent eeb315d
@alloy authored
View
2  Rakefile
@@ -16,6 +16,8 @@ Motion::Project::App.setup do |app|
app/app_delegate.rb
}
app.frameworks += %w{ CoreData }
+
+ app.vendor_project('ext', :static)
end
task 'spec' do
View
42 app/managed_object.rb
@@ -1,3 +1,23 @@
+class Class
+ def defineClassMethod(name, &block)
+ # This is really only needed if/when we need to eval it in the context of
+ # the instance. Until then we'll optimize by simply using the block as
+ # passed by the caller and let the code there deal with it.
+ #
+ #ClassExt.defineRubyClassMethod(lambda { |_self| _self.instance_eval(&block) }, withSelector:name, onClass:self)
+ ClassExt.defineRubyClassMethod(block, withSelector:name, onClass:self)
+ end
+
+ def defineInstanceMethod(name, &block)
+ # This is really only needed if/when we need to eval it in the context of
+ # the instance. Until then we'll optimize by simply using the block as
+ # passed by the caller and let the code there deal with it.
+ #
+ #ClassExt.defineRubyInstanceMethod(lambda { |_self| _self.instance_eval(&block) }, withSelector:name, onClass:self)
+ ClassExt.defineRubyInstanceMethod(block, withSelector:name, onClass:self)
+ end
+end
+
module MotionData
module CoreTypes
@@ -47,6 +67,12 @@ def hasOne(name, options = {})
def hasMany(name, options = {})
#puts "#{self.name} has many `#{name}' (#{options.inspect})"
entityDescription.hasMany(name, options)
+ klass = self
+ defineInstanceMethod(name) do |_self|
+ # TODO will/did access
+ set = _self.primitiveValueForKey(name.to_s)
+ Scope::Relationship.alloc.initWithTarget(set, relationshipName:name, owner:_self, ownerClass:klass)
+ end
end
def property(name, type, options = {})
@@ -68,21 +94,11 @@ def scopes
@scopes ||= {}
end
- # Adds a named scope to the class.
+ # Adds a named scope to the class and makes it available as a class
+ # method named after the scope.
def scope(name, scope)
scopes[name] = scope
- end
-
- # Returns a scope that matches the method name if one exists.
- #
- # TODO Until RubyMotion allows the use of define_method, this is the best
- # we can do.
- def method_missing(method, *args, &block)
- if scope = scopes[method]
- scope
- else
- super
- end
+ defineClassMethod(name) { |_self| scope }
end
end
View
10 ext/define_method.h
@@ -0,0 +1,10 @@
+#import <Foundation/Foundation.h>
+
+typedef id(^rubyMethodBlock)(id);
+
+@interface ClassExt : NSObject
+
++ (void)defineRubyClassMethod:(rubyMethodBlock)block withSelector:(SEL)selector onClass:(Class)klass;
++ (void)defineRubyInstanceMethod:(rubyMethodBlock)block withSelector:(SEL)selector onClass:(Class)klass;
+
+@end
View
17 ext/define_method.m
@@ -0,0 +1,17 @@
+#import "define_method.h"
+#import <objc/runtime.h>
+
+@implementation ClassExt
+
++ (void)defineRubyClassMethod:(rubyMethodBlock)block withSelector:(SEL)selector onClass:(Class)klass;
+{
+ [ClassExt defineRubyInstanceMethod:block withSelector:selector onClass:object_getClass(klass)];
+}
+
++ (void)defineRubyInstanceMethod:(rubyMethodBlock)block withSelector:(SEL)selector onClass:(Class)klass;
+{
+ IMP imp = imp_implementationWithBlock(block);
+ class_addMethod(klass, selector, (IMP)imp, "@@:");
+}
+
+@end
View
14 spec/managed_object_spec.rb
@@ -51,14 +51,14 @@ module MotionData
it "returns a Scope::Relationship instead of the normal Core Data set" do
author = Author.new
- author.relationship(:articles).should.be.instance_of Scope::Relationship
- author.relationship(:articles).owner.should == author
- author.relationship(:articles).ownerClass.should == Author
- author.relationship(:articles).to_a.should == []
+ author.articles.should.be.instance_of Scope::Relationship
+ author.articles.owner.should == author
+ author.articles.ownerClass.should == Author
+ author.articles.to_a.should == []
- article1 = author.relationship(:articles).new(:title => 'article1')
- article2 = author.relationship(:articles).new(:title => 'article2')
- author.relationship(:articles).withTitles.to_a.should == [article1, article2]
+ #article1 = author.articles.new(:title => 'article1')
+ #article2 = author.articles.new(:title => 'article2')
+ #author.articles.withTitles.to_a.should == [article1, article2]
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.