Permalink
Browse files

Build scopes from hashes, predicates, or other Scopes.

  • Loading branch information...
1 parent 0989fd3 commit c15249961ff3c258fc1f554f5dbd267cf5572c5a @alloy committed Aug 11, 2012
Showing with 66 additions and 27 deletions.
  1. +1 −0 Rakefile
  2. +13 −27 app/{fetch_request.rb → scope.rb}
  3. +52 −0 spec/scope_spec.rb
View
@@ -10,6 +10,7 @@ Motion::Project::App.setup do |app|
app/context.rb
app/predicate.rb
app/managed_object.rb
+ app/scope.rb
app/article.rb
app/author.rb
@@ -1,9 +1,11 @@
module MotionData
class Scope
+ include Predicate::ComparableKeyPathExpression::Mixin
+
attr_reader :target, :predicate, :sortDescriptors, :context
def initWithTarget(target)
- initWithTarget(target, predicate:nil, sortDescriptors:nil, inContext:MotionData::Context.current)
+ initWithTarget(target, predicate:nil, sortDescriptors:nil, inContext:Context.current)
end
def initWithTarget(target, predicate:predicate, sortDescriptors:sortDescriptors, inContext:context)
@@ -19,38 +21,22 @@ def initWithTarget(target, predicate:predicate, sortDescriptors:sortDescriptors,
def where(conditions)
predicate = case conditions
when Hash
- NSCompoundPredicate.andPredicateWithSubpredicates(conditions.map do |key, value|
- lhs = NSExpression.expressionForKeyPath(key)
- rhs = NSExpression.expressionForConstantValue(value)
- NSComparisonPredicate.predicateWithLeftExpression(lhs,
- rightExpression:rhs,
- modifier:NSDirectPredicateModifier,
- type:NSEqualToPredicateOperatorType,
- options:0)
+ Predicate::Compound.andPredicateWithSubpredicates(conditions.map do |kp, value|
+ keyPath(kp) == value
end)
when NSPredicate
conditions
when Scope
-
+ conditions.predicate
end
- if @predicate
- predicate = NSCompoundPredicate.andPredicateWithSubpredicates([@predicate, predicate])
- end
-
+ predicate = @predicate.and(predicate) if @predicate
Scope.alloc.initWithTarget(@target,
predicate:predicate,
sortDescriptors:@sortDescriptors,
inContext:@context)
end
- # Add finder conditions as a hash of requirements, a Scope, or a NSPredicate.
- #
- # The conditions are added using `OR`.
- def or(conditions)
-
- end
-
# Sort ascending by an attribute, or a NSSortDescriptor.
def sortBy(attribute)
sortBy(attribute, ascending:true)
@@ -81,12 +67,12 @@ def controller(options = {})
cacheName:options[:cacheName])
end
- class ToManyRelationship < FetchRequest
- # Returns the relationship set, normally provided by a Core Data to-many
- # relationship.
- def set
+ #class ToManyRelationship < Scope
+ ## Returns the relationship set, normally provided by a Core Data to-many
+ ## relationship.
+ #def set
- end
- end
+ #end
+ #end
end
end
View
@@ -0,0 +1,52 @@
+module MotionData
+
+ describe Scope do
+ extend Predicate::ComparableKeyPathExpression::Mixin
+
+ it "initializes with a class target and current context" do
+ scope = Scope.alloc.initWithTarget(Author)
+ scope.target.should == Author
+ scope.context.should == Context.current
+ end
+ end
+
+ describe Scope, "when building a new scope by applying finder options" do
+ extend Predicate::ComparableKeyPathExpression::Mixin
+
+ it "from a hash" do
+ scope1 = Scope.alloc.initWithTarget(Author)
+
+ scope2 = scope1.where(:name => 'bob', :amount => 42)
+ scope2.should.not == scope1
+ scope2.predicate.predicateFormat.should == 'name == "bob" AND amount == 42'
+
+ scope3 = scope2.where(:enabled => true)
+ scope3.should.not == scope2
+ scope3.predicate.predicateFormat.should == '(name == "bob" AND amount == 42) AND (enabled == 1)'
+ end
+
+ it "from a predicate" do
+ scope1 = Scope.alloc.initWithTarget(Author)
+
+ #scope2 = scope1.where(( value(:name) != 'bob' ).or( value(:amount) > 42 ))
+ scope2 = scope1.where(( key(:name) != 'bob' ).or( key(:amount) > 42 ))
+ scope2.should.not == scope1
+ scope2.predicate.predicateFormat.should == 'name != "bob" OR amount > 42'
+
+ scope3 = scope2.where( key(:enabled) == true )
+ scope3.should.not == scope2
+ scope3.predicate.predicateFormat.should == '(name != "bob" OR amount > 42) AND enabled == 1'
+ end
+
+ it "from a scope" do
+ scope1 = Scope.alloc.initWithTarget(Author)
+ scope2 = scope1.where(( key(:name).caseInsensitive != 'bob' ).or( key(:amount) > 42 ))
+ scope3 = scope1.where(( key(:enabled) == true ).and( key(:title) != nil ))
+
+ scope4 = scope3.where(scope2)
+ scope4.should.not == scope3
+ scope4.predicate.predicateFormat.should == '(enabled == 1 AND title != nil) AND (name !=[c] "bob" OR amount > 42)'
+ end
+ end
+
+end

0 comments on commit c152499

Please sign in to comment.