cdq 0.1.2 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/LICENSE +21 -0
- data/README.md +206 -58
- data/lib/cdq/cli.rb +1 -13
- data/lib/cdq/version.rb +1 -1
- data/motion/cdq.rb +38 -3
- data/motion/cdq/context.rb +5 -0
- data/motion/cdq/partial_predicate.rb +64 -21
- data/motion/cdq/query.rb +69 -15
- data/motion/cdq/targeted_query.rb +0 -2
- data/templates/model/spec/models/name.rb +1 -1
- metadata +12 -53
- data/.gitignore +0 -12
- data/.travis.yml +0 -2
- data/Gemfile +0 -7
- data/Gemfile.lock +0 -32
- data/Rakefile +0 -28
- data/app/app_delegate.rb +0 -13
- data/app/test_models.rb +0 -15
- data/cdq.gemspec +0 -20
- data/resources/CDQ.xcdatamodeld/.xccurrentversion +0 -8
- data/resources/CDQ.xcdatamodeld/0.0.1.xcdatamodel/contents +0 -34
- data/resources/Default-568h@2x.png +0 -0
- data/resources/KEEPME +0 -0
- data/schemas/001_baseline.rb +0 -44
- data/spec/cdq/collection_proxy_spec.rb +0 -51
- data/spec/cdq/config_spec.rb +0 -74
- data/spec/cdq/context_spec.rb +0 -92
- data/spec/cdq/managed_object_spec.rb +0 -81
- data/spec/cdq/model_spec.rb +0 -14
- data/spec/cdq/module_spec.rb +0 -44
- data/spec/cdq/object_proxy_spec.rb +0 -37
- data/spec/cdq/object_spec.rb +0 -58
- data/spec/cdq/partial_predicate_spec.rb +0 -52
- data/spec/cdq/query_spec.rb +0 -127
- data/spec/cdq/relationship_query_spec.rb +0 -75
- data/spec/cdq/store_spec.rb +0 -39
- data/spec/cdq/targeted_query_spec.rb +0 -120
- data/spec/helpers/thread_helper.rb +0 -16
- data/spec/integration_spec.rb +0 -38
data/spec/cdq/model_spec.rb
DELETED
data/spec/cdq/module_spec.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
|
4
|
-
describe "CDQ Magic Method" do
|
5
|
-
|
6
|
-
before do
|
7
|
-
class << Author
|
8
|
-
include CDQ
|
9
|
-
end
|
10
|
-
|
11
|
-
class << self
|
12
|
-
include CDQ
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
it "wraps an NSManagedObject class in a CDQTargetedQuery" do
|
17
|
-
cdq(Author).class.should == CDQTargetedQuery
|
18
|
-
end
|
19
|
-
|
20
|
-
it "treats a string as an entity name and returns a CDQTargetedQuery" do
|
21
|
-
cdq('Author').class.should == CDQTargetedQuery
|
22
|
-
end
|
23
|
-
|
24
|
-
it "treats a symbol as an attribute key and returns a CDQPartialPredicate" do
|
25
|
-
cdq(:name).class.should == CDQPartialPredicate
|
26
|
-
end
|
27
|
-
|
28
|
-
it "passes through existing CDQObjects unchanged" do
|
29
|
-
query = CDQQuery.new
|
30
|
-
cdq(query).should == query
|
31
|
-
end
|
32
|
-
|
33
|
-
it "uses 'self' if no object passed in" do
|
34
|
-
Author.cdq.class.should == CDQTargetedQuery
|
35
|
-
end
|
36
|
-
|
37
|
-
it "works with entities that do not have a specific implementation class" do
|
38
|
-
cdq('Publisher').class.should == CDQTargetedQuery
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
|
@@ -1,37 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
describe "CDQ Object Proxy" do
|
4
|
-
|
5
|
-
before do
|
6
|
-
class << self
|
7
|
-
include CDQ
|
8
|
-
end
|
9
|
-
|
10
|
-
cdq.setup
|
11
|
-
|
12
|
-
@author = Author.create(name: "Stephen King")
|
13
|
-
@article = Article.create(title: "IT", author: @author)
|
14
|
-
|
15
|
-
@op = CDQObjectProxy.new(@author)
|
16
|
-
end
|
17
|
-
|
18
|
-
after do
|
19
|
-
cdq.reset!
|
20
|
-
end
|
21
|
-
|
22
|
-
it "wraps an NSManagedObject" do
|
23
|
-
@op.get.should == @author
|
24
|
-
end
|
25
|
-
|
26
|
-
it "wraps relations in CDQRelationshipQuery objects" do
|
27
|
-
@op.articles.class.should == CDQRelationshipQuery
|
28
|
-
@op.articles.first.should == @article
|
29
|
-
end
|
30
|
-
|
31
|
-
it "can delete the underlying object" do
|
32
|
-
@op.destroy
|
33
|
-
Author.count.should == 0
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
data/spec/cdq/object_spec.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
|
4
|
-
describe "CDQ Object" do
|
5
|
-
|
6
|
-
before do
|
7
|
-
class << self
|
8
|
-
include CDQ
|
9
|
-
end
|
10
|
-
|
11
|
-
cdq.setup
|
12
|
-
end
|
13
|
-
|
14
|
-
after do
|
15
|
-
cdq.reset!
|
16
|
-
end
|
17
|
-
|
18
|
-
it "has a contexts method" do
|
19
|
-
cdq.contexts.class.should == CDQContextManager
|
20
|
-
end
|
21
|
-
|
22
|
-
it "has a stores method" do
|
23
|
-
cdq.stores.class.should == CDQStoreManager
|
24
|
-
end
|
25
|
-
|
26
|
-
it "has a models method" do
|
27
|
-
cdq.models.class.should == CDQModelManager
|
28
|
-
end
|
29
|
-
|
30
|
-
it "can override model" do
|
31
|
-
model = cdq.models.current
|
32
|
-
|
33
|
-
cdq.reset!
|
34
|
-
|
35
|
-
cdq.setup(model: model)
|
36
|
-
cdq.models.current.should == model
|
37
|
-
end
|
38
|
-
|
39
|
-
it "can override store" do
|
40
|
-
store = cdq.stores.current
|
41
|
-
|
42
|
-
cdq.reset!
|
43
|
-
|
44
|
-
cdq.setup(store: store)
|
45
|
-
cdq.stores.current.should == store
|
46
|
-
end
|
47
|
-
|
48
|
-
it "can override context" do
|
49
|
-
context = cdq.contexts.current
|
50
|
-
|
51
|
-
cdq.reset!
|
52
|
-
|
53
|
-
cdq.setup(context: context)
|
54
|
-
cdq.contexts.current.should == context
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
describe "CDQ Partial Predicates" do
|
4
|
-
|
5
|
-
before do
|
6
|
-
@scope = CDQQuery.new
|
7
|
-
@ppred = CDQPartialPredicate.new(:count, @scope)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "is composed of a key symbol and a scope" do
|
11
|
-
@ppred.key.should == :count
|
12
|
-
@ppred.scope.should.not == nil
|
13
|
-
end
|
14
|
-
|
15
|
-
it "creates an equality predicate" do
|
16
|
-
scope = @ppred.eq(1)
|
17
|
-
scope.predicate.should == make_pred('count', NSEqualToPredicateOperatorType, 1)
|
18
|
-
|
19
|
-
scope = @ppred.equal(1)
|
20
|
-
scope.predicate.should == make_pred('count', NSEqualToPredicateOperatorType, 1)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "creates a less-than predicate" do
|
24
|
-
scope = @ppred.lt(1)
|
25
|
-
scope.predicate.should == make_pred('count', NSLessThanPredicateOperatorType, 1)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "preserves the previous scope" do
|
29
|
-
scope = CDQQuery.new(predicate: NSPredicate.predicateWithValue(false))
|
30
|
-
ppred = CDQPartialPredicate.new(:count, scope)
|
31
|
-
ppred.eq(1).predicate.should == NSCompoundPredicate.andPredicateWithSubpredicates(
|
32
|
-
[NSPredicate.predicateWithValue(false), make_pred('count', NSEqualToPredicateOperatorType, 1)]
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "works with 'or' too" do
|
37
|
-
scope = CDQQuery.new(predicate: NSPredicate.predicateWithValue(true))
|
38
|
-
ppred = CDQPartialPredicate.new(:count, scope, :or)
|
39
|
-
ppred.eq(1).predicate.should == NSCompoundPredicate.orPredicateWithSubpredicates(
|
40
|
-
[NSPredicate.predicateWithValue(true), make_pred('count', NSEqualToPredicateOperatorType, 1)]
|
41
|
-
)
|
42
|
-
end
|
43
|
-
def make_pred(key, type, value, options = 0)
|
44
|
-
NSComparisonPredicate.predicateWithLeftExpression(
|
45
|
-
NSExpression.expressionForKeyPath(key.to_s),
|
46
|
-
rightExpression:NSExpression.expressionForConstantValue(value),
|
47
|
-
modifier:NSDirectPredicateModifier,
|
48
|
-
type:type,
|
49
|
-
options:options)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
data/spec/cdq/query_spec.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
describe "CDQ Query" do
|
4
|
-
|
5
|
-
before do
|
6
|
-
@query = CDQQuery.new
|
7
|
-
end
|
8
|
-
|
9
|
-
it "creates a query with a simple true predicate" do
|
10
|
-
@query.predicate.should == nil
|
11
|
-
@query.limit.should == nil
|
12
|
-
@query.offset.should == nil
|
13
|
-
end
|
14
|
-
|
15
|
-
it "can set a limit on a query" do
|
16
|
-
@query = CDQQuery.new(limit: 1)
|
17
|
-
@query.limit.should == 1
|
18
|
-
@query.offset.should == nil
|
19
|
-
end
|
20
|
-
|
21
|
-
it "can set a offset on a query" do
|
22
|
-
@query = CDQQuery.new(offset: 1)
|
23
|
-
@query.limit.should == nil
|
24
|
-
@query.offset.should == 1
|
25
|
-
end
|
26
|
-
|
27
|
-
it "can 'and' itself with another query" do
|
28
|
-
@query = CDQQuery.new(limit: 1, offset: 1)
|
29
|
-
@other = CDQQuery.new(predicate: NSPredicate.predicateWithValue(false), limit: 2)
|
30
|
-
@compound = @query.and(@other)
|
31
|
-
@compound.predicate.should == NSPredicate.predicateWithValue(false)
|
32
|
-
@compound.limit.should == 2
|
33
|
-
@compound.offset.should == 1
|
34
|
-
end
|
35
|
-
|
36
|
-
it "can 'and' itself with an NSPredicate" do
|
37
|
-
@compound = @query.and(NSPredicate.predicateWithValue(false))
|
38
|
-
@compound.predicate.should == NSPredicate.predicateWithValue(false)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "can 'and' itself with a string-based predicate query" do
|
42
|
-
query = @query.where(:name).begins_with('foo')
|
43
|
-
compound = query.and("name != %@", 'fool')
|
44
|
-
compound.predicate.predicateFormat.should == 'name BEGINSWITH "foo" AND name != "fool"'
|
45
|
-
end
|
46
|
-
|
47
|
-
it "can 'and' itself with a hash" do
|
48
|
-
compound = @query.and(name: "foo", fee: 2)
|
49
|
-
compound.predicate.predicateFormat.should == 'name == "foo" AND fee == 2'
|
50
|
-
end
|
51
|
-
|
52
|
-
it "starts a partial predicate when 'and'-ing a symbol" do
|
53
|
-
ppred = @query.and(:name)
|
54
|
-
ppred.class.should == CDQPartialPredicate
|
55
|
-
ppred.key.should == :name
|
56
|
-
end
|
57
|
-
|
58
|
-
it "can 'or' itself with another query" do
|
59
|
-
@query = CDQQuery.new(limit: 1, offset: 1)
|
60
|
-
@other = CDQQuery.new(predicate: NSPredicate.predicateWithValue(false), limit: 2)
|
61
|
-
@compound = @query.or(@other)
|
62
|
-
@compound.predicate.should == NSPredicate.predicateWithValue(false)
|
63
|
-
@compound.limit.should == 2
|
64
|
-
@compound.offset.should == 1
|
65
|
-
end
|
66
|
-
|
67
|
-
it "can 'or' itself with an NSPredicate" do
|
68
|
-
@compound = @query.or(NSPredicate.predicateWithValue(false))
|
69
|
-
@compound.predicate.should == NSPredicate.predicateWithValue(false)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "can 'or' itself with a string-based predicate query" do
|
73
|
-
query = @query.where(:name).begins_with('foo')
|
74
|
-
compound = query.or("name != %@", 'fool')
|
75
|
-
compound.predicate.predicateFormat.should == 'name BEGINSWITH "foo" OR name != "fool"'
|
76
|
-
end
|
77
|
-
|
78
|
-
it "can sort by a key" do
|
79
|
-
@query.sort_by(:name).sort_descriptors.should == [
|
80
|
-
NSSortDescriptor.sortDescriptorWithKey('name', ascending: true)
|
81
|
-
]
|
82
|
-
end
|
83
|
-
|
84
|
-
it "can sort descending" do
|
85
|
-
@query.sort_by(:name, :desc).sort_descriptors.should == [
|
86
|
-
NSSortDescriptor.sortDescriptorWithKey('name', ascending: false)
|
87
|
-
]
|
88
|
-
end
|
89
|
-
|
90
|
-
it "can chain sorts" do
|
91
|
-
@query.sort_by(:name).sort_by(:title).sort_descriptors.should == [
|
92
|
-
NSSortDescriptor.sortDescriptorWithKey('name', ascending: true),
|
93
|
-
NSSortDescriptor.sortDescriptorWithKey('title', ascending: true)
|
94
|
-
]
|
95
|
-
end
|
96
|
-
|
97
|
-
it "reuses the previous key when calling 'and' or 'or' with no arguments" do
|
98
|
-
compound = @query.where(:name).begins_with('foo').and.ne('fool')
|
99
|
-
compound.predicate.predicateFormat.should == 'name BEGINSWITH "foo" AND name != "fool"'
|
100
|
-
|
101
|
-
compound = @query.where(:name).begins_with('foo').or.eq('loofa')
|
102
|
-
compound.predicate.predicateFormat.should == 'name BEGINSWITH "foo" OR name == "loofa"'
|
103
|
-
end
|
104
|
-
|
105
|
-
it "handles complex examples" do
|
106
|
-
query1 = CDQQuery.new
|
107
|
-
query2 = query1.where(CDQQuery.new.where(:name).ne('bob', NSCaseInsensitivePredicateOption).or(:amount).gt(42).sort_by(:name))
|
108
|
-
query3 = query1.where(CDQQuery.new.where(:enabled).eq(true).and(:'job.title').ne(nil).sort_by(:amount, :desc))
|
109
|
-
|
110
|
-
query4 = query3.where(query2)
|
111
|
-
query4.predicate.predicateFormat.should == '(enabled == 1 AND job.title != nil) AND (name !=[c] "bob" OR amount > 42)'
|
112
|
-
query4.sort_descriptors.should == [
|
113
|
-
NSSortDescriptor.alloc.initWithKey('amount', ascending:false),
|
114
|
-
NSSortDescriptor.alloc.initWithKey('name', ascending:true)
|
115
|
-
]
|
116
|
-
end
|
117
|
-
|
118
|
-
it "can make a new query with a new limit" do:w
|
119
|
-
@query = CDQQuery.new
|
120
|
-
new_query = @query.limit(1)
|
121
|
-
|
122
|
-
new_query.limit.should == 1
|
123
|
-
new_query.offset.should == nil
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
|
4
|
-
describe "CDQ Relationship Query" do
|
5
|
-
|
6
|
-
before do
|
7
|
-
|
8
|
-
class << self
|
9
|
-
include CDQ
|
10
|
-
end
|
11
|
-
|
12
|
-
cdq.setup
|
13
|
-
|
14
|
-
@author = Author.create(name: "eecummings")
|
15
|
-
@article1 = @author.articles.create(author: @author, body: "", published: true, publishedAt: Time.local(1922), title: "The Enormous Room")
|
16
|
-
|
17
|
-
cdq.save(always_wait: true)
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
after do
|
22
|
-
cdq.reset!
|
23
|
-
end
|
24
|
-
|
25
|
-
it "performs queries against the target entity" do
|
26
|
-
@rq = CDQRelationshipQuery.new(@author, 'articles')
|
27
|
-
@rq.first.should != nil
|
28
|
-
@rq.first.class.should == Article_Article_
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should be able to use named scopes" do
|
32
|
-
cdq(@author).articles.all_published.array.should == [@article1]
|
33
|
-
end
|
34
|
-
|
35
|
-
it "can handle many-to-many correctly" do
|
36
|
-
ram = Writer.create(name: "Ram Das")
|
37
|
-
first = ram.spouses.create
|
38
|
-
second = ram.spouses.create
|
39
|
-
ram.spouses.array.should == [first, second]
|
40
|
-
cdq(first).writers.array.should == [ram]
|
41
|
-
cdq(second).writers.array.should == [ram]
|
42
|
-
cdq(first).writers.where(:name).contains("o").array.should == []
|
43
|
-
cdq(first).writers.where(:name).contains("a").array.should == [ram]
|
44
|
-
end
|
45
|
-
|
46
|
-
it "can add objects to the relationship" do
|
47
|
-
article = Article.create(body: "bank")
|
48
|
-
@author.articles.add(article)
|
49
|
-
@author.articles.where(body: "bank").first.should == article
|
50
|
-
article.author.should == @author
|
51
|
-
|
52
|
-
ram = Writer.create(name: "Ram Das")
|
53
|
-
ram.spouses.add cdq('Spouse').create
|
54
|
-
ram.spouses << cdq('Spouse').create
|
55
|
-
|
56
|
-
ram.spouses.count.should == 2
|
57
|
-
ram.spouses.first.writers.count.should == 1
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
it "iterates over ordered sets correctly" do
|
62
|
-
writer = Writer.create
|
63
|
-
two = cdq('Spouse').create(name: "1")
|
64
|
-
three = cdq('Spouse').create(name: "2")
|
65
|
-
one = writer.spouses.create(name: "3")
|
66
|
-
writer.spouses << two
|
67
|
-
writer.spouses << three
|
68
|
-
writer.spouses.map(&:name).should == ["3", "1", "2"]
|
69
|
-
writer.spouses.array.map(&:name).should == ["3", "1", "2"]
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|
data/spec/cdq/store_spec.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
|
2
|
-
module CDQ
|
3
|
-
|
4
|
-
describe "CDQ Store Manager" do
|
5
|
-
|
6
|
-
before do
|
7
|
-
CDQ.cdq.setup
|
8
|
-
@sm = CDQStoreManager.new(model_manager: CDQ.cdq.models)
|
9
|
-
end
|
10
|
-
|
11
|
-
after do
|
12
|
-
CDQ.cdq.reset!
|
13
|
-
end
|
14
|
-
|
15
|
-
it "can set up a store coordinator with default name" do
|
16
|
-
@sm.current.should != nil
|
17
|
-
@sm.current.class.should == NSPersistentStoreCoordinator
|
18
|
-
end
|
19
|
-
|
20
|
-
it "rejects attempt to create without a valid model" do
|
21
|
-
c = CDQConfig.new(name: "foo")
|
22
|
-
mm = CDQModelManager.new(config: c)
|
23
|
-
sm = CDQStoreManager.new(config: c, model_manager: mm)
|
24
|
-
should.raise do
|
25
|
-
sm.current
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it "permits setting custom store manager" do
|
30
|
-
nsm = CDQStoreManager.new(model: nil)
|
31
|
-
should.not.raise do
|
32
|
-
nsm.current = @sm.current
|
33
|
-
nsm.current
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|