cdq 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|