babik 0.1.0
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 +7 -0
- data/Gemfile +16 -0
- data/README.md +718 -0
- data/Rakefile +18 -0
- data/lib/babik.rb +122 -0
- data/lib/babik/database.rb +16 -0
- data/lib/babik/queryset.rb +154 -0
- data/lib/babik/queryset/components/aggregation.rb +172 -0
- data/lib/babik/queryset/components/limit.rb +22 -0
- data/lib/babik/queryset/components/order.rb +161 -0
- data/lib/babik/queryset/components/projection.rb +118 -0
- data/lib/babik/queryset/components/select_related.rb +78 -0
- data/lib/babik/queryset/components/sql_renderer.rb +99 -0
- data/lib/babik/queryset/components/where.rb +43 -0
- data/lib/babik/queryset/lib/association/foreign_association_chain.rb +97 -0
- data/lib/babik/queryset/lib/association/select_related_association_chain.rb +32 -0
- data/lib/babik/queryset/lib/condition.rb +103 -0
- data/lib/babik/queryset/lib/field.rb +34 -0
- data/lib/babik/queryset/lib/join/association_joiner.rb +39 -0
- data/lib/babik/queryset/lib/join/join.rb +86 -0
- data/lib/babik/queryset/lib/selection/config.rb +19 -0
- data/lib/babik/queryset/lib/selection/foreign_selection.rb +39 -0
- data/lib/babik/queryset/lib/selection/local_selection.rb +40 -0
- data/lib/babik/queryset/lib/selection/operation/base.rb +126 -0
- data/lib/babik/queryset/lib/selection/operation/date.rb +178 -0
- data/lib/babik/queryset/lib/selection/operation/operations.rb +201 -0
- data/lib/babik/queryset/lib/selection/operation/regex.rb +58 -0
- data/lib/babik/queryset/lib/selection/path/foreign_path.rb +50 -0
- data/lib/babik/queryset/lib/selection/path/local_path.rb +44 -0
- data/lib/babik/queryset/lib/selection/path/path.rb +23 -0
- data/lib/babik/queryset/lib/selection/select_related_selection.rb +38 -0
- data/lib/babik/queryset/lib/selection/selection.rb +19 -0
- data/lib/babik/queryset/lib/update/assignment.rb +108 -0
- data/lib/babik/queryset/mixins/aggregatable.rb +17 -0
- data/lib/babik/queryset/mixins/bounded.rb +38 -0
- data/lib/babik/queryset/mixins/clonable.rb +52 -0
- data/lib/babik/queryset/mixins/countable.rb +44 -0
- data/lib/babik/queryset/mixins/deletable.rb +13 -0
- data/lib/babik/queryset/mixins/distinguishable.rb +27 -0
- data/lib/babik/queryset/mixins/filterable.rb +51 -0
- data/lib/babik/queryset/mixins/limitable.rb +88 -0
- data/lib/babik/queryset/mixins/lockable.rb +31 -0
- data/lib/babik/queryset/mixins/none.rb +16 -0
- data/lib/babik/queryset/mixins/projectable.rb +34 -0
- data/lib/babik/queryset/mixins/related_selector.rb +28 -0
- data/lib/babik/queryset/mixins/set_operations.rb +32 -0
- data/lib/babik/queryset/mixins/sortable.rb +49 -0
- data/lib/babik/queryset/mixins/sql_renderizable.rb +17 -0
- data/lib/babik/queryset/mixins/updatable.rb +14 -0
- data/lib/babik/queryset/templates/default/delete/main.sql.erb +14 -0
- data/lib/babik/queryset/templates/default/select/components/aggregation.sql.erb +5 -0
- data/lib/babik/queryset/templates/default/select/components/from.sql.erb +16 -0
- data/lib/babik/queryset/templates/default/select/components/from_set.sql.erb +3 -0
- data/lib/babik/queryset/templates/default/select/components/from_table.sql.erb +2 -0
- data/lib/babik/queryset/templates/default/select/components/limit.sql.erb +10 -0
- data/lib/babik/queryset/templates/default/select/components/order_by.sql.erb +9 -0
- data/lib/babik/queryset/templates/default/select/components/projection.sql.erb +7 -0
- data/lib/babik/queryset/templates/default/select/components/select_related.sql.erb +26 -0
- data/lib/babik/queryset/templates/default/select/components/where.sql.erb +39 -0
- data/lib/babik/queryset/templates/default/select/main.sql.erb +42 -0
- data/lib/babik/queryset/templates/default/update/main.sql.erb +15 -0
- data/lib/babik/queryset/templates/mssql/select/components/limit.sql.erb +8 -0
- data/lib/babik/queryset/templates/mssql/select/components/order_by.sql.erb +21 -0
- data/lib/babik/queryset/templates/mysql2/delete/main.sql.erb +15 -0
- data/lib/babik/queryset/templates/mysql2/update/main.sql.erb +18 -0
- data/lib/babik/queryset/templates/sqlite3/select/components/from_set.sql.erb +5 -0
- data/test/config/db/schema.rb +83 -0
- data/test/config/models/bad_post.rb +5 -0
- data/test/config/models/bad_tag.rb +5 -0
- data/test/config/models/category.rb +4 -0
- data/test/config/models/geozone.rb +6 -0
- data/test/config/models/group.rb +5 -0
- data/test/config/models/group_user.rb +5 -0
- data/test/config/models/post.rb +24 -0
- data/test/config/models/post_tag.rb +5 -0
- data/test/config/models/tag.rb +5 -0
- data/test/config/models/user.rb +6 -0
- data/test/delete/delete_test.rb +60 -0
- data/test/delete/foreign_conditions_delete_test.rb +57 -0
- data/test/delete/local_conditions_delete_test.rb +20 -0
- data/test/enable_coverage.rb +17 -0
- data/test/lib/selection/operation/log/test-queries.log +1 -0
- data/test/lib/selection/operation/test_date.rb +131 -0
- data/test/lib/selection/operation/test_regex.rb +55 -0
- data/test/other/clone_test.rb +129 -0
- data/test/other/escape_test.rb +21 -0
- data/test/other/inverse_of_required_test.rb +33 -0
- data/test/select/aggregate_test.rb +151 -0
- data/test/select/bounds_test.rb +46 -0
- data/test/select/count_test.rb +147 -0
- data/test/select/distinct_test.rb +38 -0
- data/test/select/exclude_test.rb +72 -0
- data/test/select/filter_from_object_test.rb +125 -0
- data/test/select/filter_test.rb +207 -0
- data/test/select/for_update_test.rb +19 -0
- data/test/select/foreign_selection_test.rb +60 -0
- data/test/select/get_test.rb +40 -0
- data/test/select/limit_test.rb +109 -0
- data/test/select/local_selection_test.rb +24 -0
- data/test/select/lookup_test.rb +208 -0
- data/test/select/none_test.rb +40 -0
- data/test/select/order_test.rb +165 -0
- data/test/select/project_test.rb +107 -0
- data/test/select/select_related_test.rb +124 -0
- data/test/select/subquery_test.rb +50 -0
- data/test/set_operations/basic_usage_test.rb +121 -0
- data/test/test_helper.rb +55 -0
- data/test/update/update_test.rb +93 -0
- metadata +278 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Check the quotes and strings ar correctly escaped.
|
7
|
+
class EscapeTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
User.create!(first_name: 'Athos')
|
11
|
+
User.create!(first_name: 'Porthos')
|
12
|
+
User.create!(first_name: 'Aramis')
|
13
|
+
User.create!(first_name: "D'Artagnan")
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_escape_value
|
17
|
+
users = User.objects.filter(first_name: "D'Artagnan")
|
18
|
+
assert_equal 1, users.count
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Check that inverse_of is required in all associations
|
7
|
+
class InverseOfRequiredTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
main_category = Category.create!(name: 'Category not used')
|
11
|
+
bad_post = BadPost.create!(title: 'This is a bad post', category: main_category)
|
12
|
+
BadTag.create!(name: 'bad tag 1', bad_post: bad_post)
|
13
|
+
BadTag.create!(name: 'bad tag 2', bad_post: bad_post)
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
BadTag.delete_all
|
18
|
+
BadPost.delete_all
|
19
|
+
Category.delete_all
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_association_without_inverse
|
23
|
+
exception = assert_raises RuntimeError do
|
24
|
+
bad_post = BadPost.all.first
|
25
|
+
bad_post.objects(:bad_tags)
|
26
|
+
end
|
27
|
+
assert_equal(
|
28
|
+
'Relationship bad_tags of model BadPost has no inverse_of option.',
|
29
|
+
exception.message
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of aggregate method
|
7
|
+
class AggregateTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@caesar = User.create!(first_name: 'Julius', last_name: 'Caesar', email: 'backstabbed@example.com')
|
11
|
+
(1..7).each do |book_i|
|
12
|
+
post = Post.create!(title: "Commentarii de Bello Gallico #{book_i}", author: @caesar, stars: [book_i, 5].min)
|
13
|
+
post.add_tag_by_name('war')
|
14
|
+
post.add_tag_by_name('gallic')
|
15
|
+
post.add_tag_by_name('tribes')
|
16
|
+
post.add_tag_by_name('victory')
|
17
|
+
post.add_tag_by_name('campaign')
|
18
|
+
post.add_tag_by_name('biography')
|
19
|
+
end
|
20
|
+
|
21
|
+
@aulus = User.create!(first_name: 'Aulus', last_name: 'Hirtius', email: 'aulushirtius@example.com')
|
22
|
+
last_post = Post.create!(title: 'Commentarii de Bello Gallico 8', author: @aulus)
|
23
|
+
last_post.add_tag_by_name('war')
|
24
|
+
last_post.add_tag_by_name('last_book')
|
25
|
+
end
|
26
|
+
|
27
|
+
def teardown
|
28
|
+
Tag.destroy_all
|
29
|
+
Post.destroy_all
|
30
|
+
User.destroy_all
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_local_avg
|
34
|
+
stars = @caesar.objects(:posts).map(&:stars)
|
35
|
+
avg_stars = stars.reduce(:+) / stars.length.to_f
|
36
|
+
avg_starts_aggregation = @caesar
|
37
|
+
.objects(:posts)
|
38
|
+
.aggregate(avg_stars: Babik::QuerySet.agg(:avg, 'stars'))
|
39
|
+
assert_equal avg_stars.round(4), avg_starts_aggregation[:avg_stars].round(4)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_foreign_avg
|
43
|
+
stars = @caesar.objects(:posts).map(&:stars)
|
44
|
+
avg_stars = stars.reduce(:+) / stars.length.to_f
|
45
|
+
avg_starts_aggregation = User
|
46
|
+
.objects
|
47
|
+
.filter(id: @caesar.id)
|
48
|
+
.aggregate(avg_stars: Babik::QuerySet.agg(:avg, 'posts::stars'))
|
49
|
+
assert_equal avg_stars.round(4), avg_starts_aggregation[:avg_stars].round(4)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_simplified_foreign_avg
|
53
|
+
stars = @caesar.objects(:posts).map(&:stars)
|
54
|
+
avg_stars = stars.reduce(:+) / stars.length.to_f
|
55
|
+
avg_starts_aggregation = @caesar
|
56
|
+
.objects
|
57
|
+
.aggregate(avg_stars: Babik::QuerySet.agg(:avg, 'posts::stars'))
|
58
|
+
assert_equal avg_stars.round(4), avg_starts_aggregation[:avg_stars].round(4)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_local_distinct_count
|
62
|
+
# Julius Caesar has all types of value of stars
|
63
|
+
# As he has posts with all stars, it should be 5
|
64
|
+
count_aggregation = @caesar
|
65
|
+
.objects
|
66
|
+
.project(:stars)
|
67
|
+
.aggregate(
|
68
|
+
caesar_count_distinct_stars:
|
69
|
+
Babik::QuerySet.agg(:count_distinct, 'posts::stars')
|
70
|
+
)
|
71
|
+
assert_equal 5, count_aggregation[:caesar_count_distinct_stars]
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_foreign_distinct_count
|
75
|
+
# Julius Caesar has 6 tags in his posts, it should be 6
|
76
|
+
count_aggregation = @caesar
|
77
|
+
.objects
|
78
|
+
.aggregate(
|
79
|
+
caesar_count_distinct_tags:
|
80
|
+
Babik::QuerySet.agg(:count_distinct, 'posts::tags::id')
|
81
|
+
)
|
82
|
+
assert_equal 6, count_aggregation[:caesar_count_distinct_tags]
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_foreign_count
|
86
|
+
# Julius Caesar has 6 tags in his posts, it should be 6
|
87
|
+
count_aggregation = @caesar
|
88
|
+
.objects
|
89
|
+
.aggregate(
|
90
|
+
caesar_count_tags:
|
91
|
+
Babik::QuerySet.agg(:count, 'posts::tags::id')
|
92
|
+
)
|
93
|
+
assert_equal @caesar.objects(:posts).count * 6, count_aggregation[:caesar_count_tags]
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_max
|
97
|
+
max_stars = @caesar.objects(:posts).map(&:stars).max
|
98
|
+
max_stars_agg = @caesar.objects(:posts)
|
99
|
+
.aggregate(max_stars: Babik::QuerySet.agg(:max, 'stars'))[:max_stars]
|
100
|
+
assert_equal max_stars, max_stars_agg
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_min
|
104
|
+
min_stars = @caesar.objects(:posts).map(&:stars).min
|
105
|
+
min_stars_agg = @caesar.objects(:posts)
|
106
|
+
.aggregate(min_stars: Babik::QuerySet::Min.new('stars'))[:min_stars]
|
107
|
+
assert_equal min_stars, min_stars_agg
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_sum
|
111
|
+
sum_stars = @caesar.objects(:posts).map(&:stars).inject(:+)
|
112
|
+
sum_stars_agg = @caesar.objects(:posts)
|
113
|
+
.aggregate(sum_stars: Babik::QuerySet::Sum.new('stars'))[:sum_stars]
|
114
|
+
assert_equal sum_stars, sum_stars_agg
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_sum_max_min
|
118
|
+
sum_stars = @caesar.objects(:posts).map(&:stars).inject(:+)
|
119
|
+
max_stars = @caesar.objects(:posts).map(&:stars).max
|
120
|
+
min_stars = @caesar.objects(:posts).map(&:stars).min
|
121
|
+
|
122
|
+
|
123
|
+
max_min_stars_agg = @caesar.objects(:posts)
|
124
|
+
.aggregate(
|
125
|
+
sum_stars: Babik::QuerySet::Sum.new('stars'),
|
126
|
+
max_stars: Babik::QuerySet::Max.new('stars'),
|
127
|
+
min_stars: Babik::QuerySet::Min.new('stars')
|
128
|
+
)
|
129
|
+
assert_equal sum_stars, max_min_stars_agg[:sum_stars]
|
130
|
+
assert_equal max_stars, max_min_stars_agg[:max_stars]
|
131
|
+
assert_equal min_stars, max_min_stars_agg[:min_stars]
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_std_dev
|
135
|
+
if %w[postgres, mysql2].include?(Babik::Database.config[:adapter])
|
136
|
+
std_dev_var_agg = @caesar.objects(:posts)
|
137
|
+
.aggregate(
|
138
|
+
std_dev_stars: Babik::QuerySet::StdDev.new('stars'),
|
139
|
+
std_dev_sample_stars: Babik::QuerySet::StdDevSample.new('stars'),
|
140
|
+
var_stars: Babik::QuerySet::Var.new('stars'),
|
141
|
+
var_sample_stars: Babik::QuerySet::VarSample.new('stars'),
|
142
|
+
)
|
143
|
+
|
144
|
+
assert_in_delta 1.4982983545287878, std_dev_var_agg[:std_dev_stars]
|
145
|
+
assert_in_delta 1.618347187425374, std_dev_var_agg[:std_dev_sample_stars]
|
146
|
+
assert_in_delta 2.2448979591836733, std_dev_var_agg[:var_stars]
|
147
|
+
assert_in_delta 2.244897959183673, std_dev_var_agg[:var_sample_stars]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of first, last, earliest and latest methods
|
7
|
+
class BoundsTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@cervantes = User.create!(first_name: 'Miguel', last_name: 'De Cervantes y Saavedra')
|
11
|
+
Post.create!(title: 'La Galatea', author: @cervantes, stars: 3)
|
12
|
+
Post.create!(title: 'La gitanilla', author: @cervantes, stars: 3)
|
13
|
+
Post.create!(title: 'El ingenioso hidalgo Don Quijote de La Mancha', author: @cervantes, stars: 5)
|
14
|
+
Post.create!(title: 'Rinconete y Cortadillo', author: @cervantes, stars: 4)
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
Post.destroy_all
|
19
|
+
User.destroy_all
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_first_and_earliest
|
23
|
+
first_with_less_stars = Post.objects.order_by('stars').first
|
24
|
+
earliest_with_less_stars = Post.objects.earliest('stars')
|
25
|
+
latest_with_more_stars = Post.objects.latest('-stars')
|
26
|
+
assert_equal latest_with_more_stars.id, first_with_less_stars.id
|
27
|
+
assert_equal earliest_with_less_stars.id, first_with_less_stars.id
|
28
|
+
assert_equal 'La Galatea', first_with_less_stars.title
|
29
|
+
assert_equal 'La Galatea', earliest_with_less_stars.title
|
30
|
+
assert_equal 3, first_with_less_stars.stars
|
31
|
+
assert_equal 3, earliest_with_less_stars.stars
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_last_and_latest
|
35
|
+
last_with_less_stars = Post.objects.order_by('stars').last
|
36
|
+
latest_with_less_stars = Post.objects.latest('stars')
|
37
|
+
earliest_with_more_stars = Post.objects.earliest('-stars')
|
38
|
+
assert_equal earliest_with_more_stars.id, last_with_less_stars.id
|
39
|
+
assert_equal latest_with_less_stars.id, last_with_less_stars.id
|
40
|
+
assert_equal 'El ingenioso hidalgo Don Quijote de La Mancha', last_with_less_stars.title
|
41
|
+
assert_equal 'El ingenioso hidalgo Don Quijote de La Mancha', latest_with_less_stars.title
|
42
|
+
assert_equal 5, last_with_less_stars.stars
|
43
|
+
assert_equal 5, latest_with_less_stars.stars
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of count method
|
7
|
+
class CountTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@parthian_empire = GeoZone.create!(name: 'Parthian Empire')
|
11
|
+
@syria = GeoZone.create!(name: 'Syria', parent_zone: @parthian_empire)
|
12
|
+
@antioch = GeoZone.create!(name: 'Antioch', parent_zone: @syria)
|
13
|
+
@seleucus = User.create!(first_name: 'Seleucus', email: 'seleucus@example.com', zone: @antioch)
|
14
|
+
|
15
|
+
@roman_empire = GeoZone.create!(name: 'Roman Empire')
|
16
|
+
|
17
|
+
@italia = GeoZone.create!(name: 'Italia', parent_zone: @roman_empire)
|
18
|
+
@rome = GeoZone.create!(name: 'Rome', parent_zone: @italia)
|
19
|
+
|
20
|
+
@judea = GeoZone.create!(name: 'Judea', parent_zone: @roman_empire)
|
21
|
+
@jerusalem = GeoZone.create!(name: 'Jerusalem', parent_zone: @judea)
|
22
|
+
|
23
|
+
@tiberius = User.create!(first_name: 'Tiberius', email: 'tiberius@example.com', zone: @rome)
|
24
|
+
@pilate = User.create!(first_name: 'Pontius', last_name: 'Pilate', email: 'pontious@example.com', zone: @jerusalem)
|
25
|
+
@flavio = User.create!(first_name: 'Flavio', last_name: 'Josefo', email: 'flaviojosefo@example.com', zone: @jerusalem)
|
26
|
+
|
27
|
+
@noah = User.create!(first_name: 'Noah')
|
28
|
+
@noah.created_at = Time.now - 1000.days
|
29
|
+
@noah.save!
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown
|
33
|
+
@parthian_empire.destroy
|
34
|
+
@seleucus.destroy
|
35
|
+
@roman_empire.destroy
|
36
|
+
@tiberius.destroy
|
37
|
+
@pilate.destroy
|
38
|
+
@flavio.destroy
|
39
|
+
@noah.destroy
|
40
|
+
end
|
41
|
+
|
42
|
+
# Test the count is well implemented when the returned value is 0
|
43
|
+
def test_count_0
|
44
|
+
zone_non_existant_description = 'This description does not appear in any zone'
|
45
|
+
queryset = User.objects.filter(
|
46
|
+
first_name: 'Flavio',
|
47
|
+
last_name: 'Josefo',
|
48
|
+
"zone::name__different": 'Rome',
|
49
|
+
"zone::description": zone_non_existant_description
|
50
|
+
)
|
51
|
+
active_record_set = User
|
52
|
+
.joins(:zone)
|
53
|
+
.where(first_name: 'Flavio', last_name: 'Josefo', "geo_zones.description": zone_non_existant_description)
|
54
|
+
.where.not("geo_zones.name": 'Rome')
|
55
|
+
assert_equal active_record_set.count, queryset.count
|
56
|
+
assert_equal queryset.length,queryset.count
|
57
|
+
assert_equal queryset.length,queryset.size
|
58
|
+
assert queryset.empty?
|
59
|
+
assert_equal false, queryset.exists?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Test the count is well implemented when the returned value is 1
|
63
|
+
def test_count_1
|
64
|
+
queryset = User.objects.filter(
|
65
|
+
first_name: 'Flavio',
|
66
|
+
last_name: 'Josefo',
|
67
|
+
"zone::name__different": 'Madrid'
|
68
|
+
)
|
69
|
+
active_record_set = User
|
70
|
+
.joins(:zone)
|
71
|
+
.where(first_name: 'Flavio', last_name: 'Josefo')
|
72
|
+
.where.not("geo_zones.name": 'Madrid')
|
73
|
+
assert_equal active_record_set.count, queryset.count
|
74
|
+
assert_equal queryset.length, queryset.count
|
75
|
+
assert_equal queryset.length, queryset.size
|
76
|
+
assert_equal false, queryset.empty?
|
77
|
+
assert_equal true, queryset.exists?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Test the count from a deep belongs to relationship
|
81
|
+
def test_from_deep_belongs_to
|
82
|
+
queryset = User.objects.filter(
|
83
|
+
"zone::parent_zone::parent_zone::name__equals": 'Roman Empire'
|
84
|
+
)
|
85
|
+
assert_equal 3, queryset.count
|
86
|
+
assert_equal 3, queryset.size
|
87
|
+
end
|
88
|
+
|
89
|
+
# Test the count from a deep belongs to relationship
|
90
|
+
def test_or
|
91
|
+
queryset = User.objects.filter(
|
92
|
+
[
|
93
|
+
{ "zone::parent_zone::parent_zone::name__equals": 'Roman Empire' },
|
94
|
+
{ "zone::parent_zone::parent_zone::name__equals": 'Parthian Empire' }
|
95
|
+
]
|
96
|
+
)
|
97
|
+
number_of_users = 0
|
98
|
+
queryset.each do |user|
|
99
|
+
assert ['Roman Empire', 'Parthian Empire'].include?(user.zone.parent_zone.parent_zone.name)
|
100
|
+
number_of_users += 1
|
101
|
+
end
|
102
|
+
assert_equal 4, queryset.count
|
103
|
+
assert_equal 4, number_of_users
|
104
|
+
end
|
105
|
+
|
106
|
+
# Count the objects using contains
|
107
|
+
def test_lookups
|
108
|
+
assert_equal User.where('first_name LIKE ?', '%avi%').length, User.objects.filter(first_name__contains: 'avi').length
|
109
|
+
assert_equal User.where('first_name LIKE ?', 'Fla%').length, User.objects.filter(first_name__startswith: 'Fla').length
|
110
|
+
assert_equal User.where('first_name LIKE ?', '%vio').length, User.objects.filter(first_name__startswith: 'Fla').length
|
111
|
+
assert_equal User.where(first_name: 'Flavio').length, User.objects.filter(first_name: 'Flavio').length
|
112
|
+
assert_equal User.where(first_name: 'Flavio').length, User.objects.filter(first_name__exact: 'Flavio').length
|
113
|
+
assert_equal User.where(first_name: 'Flavio').length, User.objects.filter(first_name__equal: 'Flavio').length
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_lookup_isnull
|
117
|
+
assert_equal 0, User.objects.filter('zone::name': 'Rome', email__isnull: true).count
|
118
|
+
assert_equal 0, User.objects.filter('zone::name': 'Rome', email__exact: nil).count
|
119
|
+
assert_equal 1, User.objects.filter('zone::name': 'Rome', email__isnull: false).count
|
120
|
+
assert_equal 2, User.objects.filter('zone::name': 'Jerusalem', email__isnull: false).count
|
121
|
+
assert_equal 2, User.objects.filter('zone::name': 'Jerusalem').exclude(email__exact: nil).count
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_lookup_in
|
125
|
+
assert_equal 2, User.objects.filter(first_name__in: %w[Tiberius Pontius Julius Marcus]).length
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_date
|
129
|
+
today_start = Time.now.beginning_of_day
|
130
|
+
today_end = Time.now.end_of_day
|
131
|
+
today = Date.today
|
132
|
+
|
133
|
+
number_of_users = User.where('created_at >= ?', today_start).where('created_at <= ?', today_end).count
|
134
|
+
|
135
|
+
assert_equal number_of_users, User.objects.filter(created_at__gte: today_start, created_at__lte: today_end).count
|
136
|
+
assert_equal number_of_users, User.objects.filter(created_at__between: [today_start, today_end]).count
|
137
|
+
assert_equal number_of_users, User.objects.filter(created_at__date: today).count
|
138
|
+
|
139
|
+
assert_equal(
|
140
|
+
2, User
|
141
|
+
.objects
|
142
|
+
.filter(created_at__date: today)
|
143
|
+
.filter([{ first_name: 'Tiberius' }, { first_name: 'Pontius' }]).count
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of distinct method
|
7
|
+
class DistinctTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
User.create!(first_name: 'Diego', last_name: 'de Siloé')
|
11
|
+
User.create!(first_name: 'Diego', last_name: 'Velazquez')
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
User.delete_all
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_local_distinct
|
19
|
+
assert_equal 2, User.objects.filter(first_name: 'Diego').project(:first_name).count
|
20
|
+
assert_equal 1, User.objects.distinct.filter(first_name: 'Diego').project(:first_name).count
|
21
|
+
assert User.objects.distinct.filter(first_name: 'Diego').distinct?
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_local_distinct_from_queryset
|
25
|
+
diegos = User.objects.filter(first_name: 'Diego').project(:first_name).distinct
|
26
|
+
assert diegos.distinct?
|
27
|
+
refute diegos.undistinct.distinct?
|
28
|
+
assert_equal 1, diegos.count
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_local_undistinct
|
32
|
+
diegos = User.objects.filter(first_name: 'Diego').project(:first_name)
|
33
|
+
refute diegos.distinct?
|
34
|
+
assert_equal 2, diegos.count
|
35
|
+
assert_equal diegos.count, diegos.distinct.undistinct.count
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of exclude method
|
7
|
+
class ExcludeTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@asturias = GeoZone.new(name: 'Asturias')
|
11
|
+
@cantabria = GeoZone.new(name: 'Cantabria')
|
12
|
+
@cangas_de_onis = GeoZone.new(name: 'Cangas de Onís', parent_zone: @asturias)
|
13
|
+
@oviedo = GeoZone.new(name: 'Oviedo', parent_zone: @asturias)
|
14
|
+
|
15
|
+
User.create!(first_name: 'Pelayo', biography: 'Unknown origin', zone: @cangas_de_onis)
|
16
|
+
User.create!(first_name: 'Favila', biography: 'Short reign of two years, seven months and ten days', zone: @cangas_de_onis)
|
17
|
+
User.create!(first_name: 'Alfonso I', last_name: 'El Católico', biography: 'Son-in-law of Don Pelayo', zone: @cantabria)
|
18
|
+
User.create!(first_name: 'Fruela I', last_name: 'Hombre de Hierro', biography: 'Killed by conspirators', zone: @cangas_de_onis)
|
19
|
+
User.create!(first_name: 'Aurelio', biography: 'Chosen by Asturian nobility', zone: @asturias)
|
20
|
+
User.create!(first_name: 'Silo', biography: 'Peace period', zone: @asturias)
|
21
|
+
User.create!(first_name: 'Alfonso II', last_name: 'El Casto', biography: 'Discovered Saint James tomb', zone: @oviedo)
|
22
|
+
User.create!(first_name: 'Mauregato', biography: 'Paid the 100 maidens tribute to Cordova Emirate', zone: @asturias)
|
23
|
+
User.create!(first_name: 'Bermudo I', last_name: 'El Diácono', biography: 'Cultured, magnanimous and illustrated man')
|
24
|
+
User.create!(first_name: 'Nepociano', last_name: 'El usurpador')
|
25
|
+
User.create!(first_name: 'Ramiro I', last_name: 'Vara de la Justicia', zone: @oviedo)
|
26
|
+
User.create!(first_name: 'Ordoño I', biography: 'Failed first attemp to reconquer the kingdom', zone: @oviedo)
|
27
|
+
User.create!(first_name: 'Alfonso III', last_name: 'El Magno', biography: 'Last king of Independent Asturian kingdom')
|
28
|
+
User.create!(first_name: 'Fruela II', last_name: 'El leproso', biography: 'Last king of Asturian kingdom')
|
29
|
+
end
|
30
|
+
|
31
|
+
def teardown
|
32
|
+
User.delete_all
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_local_exclude
|
36
|
+
kings_with_bio_out_without_ordinal = User.objects
|
37
|
+
.filter(biography__isnull: false)
|
38
|
+
.exclude(first_name__endswith: 'I')
|
39
|
+
.order_by([:first_name, :ASC])
|
40
|
+
asturian_kings = ['Aurelio', 'Favila', 'Mauregato', 'Pelayo', 'Silo']
|
41
|
+
kings_with_bio_out_without_ordinal.each_with_index do |king, king_i|
|
42
|
+
assert_equal asturian_kings[king_i], king.first_name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_foreign_exclude
|
47
|
+
kings_with_bio_not_from_oviedo = User.objects
|
48
|
+
.filter(biography__isnull: false)
|
49
|
+
.exclude('zone::name': 'Oviedo')
|
50
|
+
.order_by([:first_name, :ASC])
|
51
|
+
asturian_kings = ['Alfonso I', 'Aurelio', 'Favila', 'Fruela I', 'Mauregato', 'Pelayo', 'Silo']
|
52
|
+
kings_with_bio_not_from_oviedo.each_with_index do |king, king_i|
|
53
|
+
assert_equal asturian_kings[king_i], king.first_name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_foreign_complex_exclude
|
58
|
+
kings_not_from_oviedo_not_named_alfonso = User.objects
|
59
|
+
.exclude(
|
60
|
+
[
|
61
|
+
{ 'zone::name': 'Oviedo' },
|
62
|
+
{ first_name__startswith: 'Alfonso' }
|
63
|
+
]
|
64
|
+
)
|
65
|
+
.order_by([:first_name, :ASC])
|
66
|
+
asturian_kings = ['Aurelio', 'Favila', 'Fruela I', 'Mauregato', 'Pelayo', 'Silo']
|
67
|
+
kings_not_from_oviedo_not_named_alfonso.each_with_index do |king, king_i|
|
68
|
+
assert_equal asturian_kings[king_i], king.first_name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|