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,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Limit method tests
|
7
|
+
class LimitTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
i = 0
|
11
|
+
while i < 100
|
12
|
+
User.create!(first_name: "User #{i + 1}", last_name: 'LimitTest user')
|
13
|
+
i += 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
User.delete_all
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_limit
|
22
|
+
page_size = 5
|
23
|
+
|
24
|
+
# Check the first page of users
|
25
|
+
first_page = User.objects.filter(last_name: 'LimitTest user').limit(page_size)
|
26
|
+
# Check with each
|
27
|
+
loops = 0
|
28
|
+
first_page.each do |user|
|
29
|
+
assert_equal "User #{loops + 1}", user.first_name
|
30
|
+
loops += 1
|
31
|
+
end
|
32
|
+
assert_equal page_size, loops
|
33
|
+
|
34
|
+
# Check the second page of users
|
35
|
+
second_page_offset = page_size
|
36
|
+
second_page = User.objects.filter(last_name: 'LimitTest user').limit(page_size, second_page_offset)
|
37
|
+
assert_equal 5, second_page.count
|
38
|
+
second_page.each_with_index do |user, user_index|
|
39
|
+
assert_equal "User #{user_index + second_page_offset + 1}", user.first_name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_limit_brackets
|
44
|
+
page_size = 5
|
45
|
+
first_page = User.objects.filter(last_name: 'LimitTest user').limit(page_size)
|
46
|
+
first_page_with_brackets = User.objects.filter(last_name: 'LimitTest user')[0..page_size]
|
47
|
+
limit_test_user = User.objects.filter(last_name: 'LimitTest user')[page_size]
|
48
|
+
assert_equal 'No user', User.objects.filter(last_name: 'LimitTest user').fetch(10_000, 'No user')
|
49
|
+
|
50
|
+
non_existent_index = User.objects.count + 100
|
51
|
+
exception = assert_raises IndexError do
|
52
|
+
User.objects.filter(last_name: 'LimitTest user').fetch(non_existent_index)
|
53
|
+
end
|
54
|
+
limit_test_count = User.objects.filter(last_name: 'LimitTest user').count
|
55
|
+
|
56
|
+
assert_equal("Index #{non_existent_index} outside of QuerySet bounds", exception.message)
|
57
|
+
assert_equal User, limit_test_user.class
|
58
|
+
assert_equal 'LimitTest user', limit_test_user.last_name
|
59
|
+
assert_equal first_page.count, first_page_with_brackets.count
|
60
|
+
|
61
|
+
second_page_offset = page_size
|
62
|
+
second_page = User.objects.filter(last_name: 'LimitTest user').limit(page_size, second_page_offset)
|
63
|
+
second_page_with_brackets = User.objects.filter(last_name: 'LimitTest user')[second_page_offset..(second_page_offset+page_size)]
|
64
|
+
assert_equal page_size, second_page.count
|
65
|
+
assert_equal second_page.count, second_page_with_brackets.count
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_limit_brackets_index
|
69
|
+
first_user = User.objects.filter(last_name: 'LimitTest user').order_by(created_at: :ASC)[0]
|
70
|
+
expected_first_user = User.where(last_name: 'LimitTest user').order('created_at ASC').first
|
71
|
+
assert_equal expected_first_user.id, first_user.id
|
72
|
+
assert_equal expected_first_user.first_name, first_user.first_name
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_is_limited
|
76
|
+
assert User.objects.filter!(last_name: 'LimitTest user').limit!(5, 10).limit?
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_unlimit
|
80
|
+
refute User.objects.filter!(last_name: 'LimitTest user').limit!(5, 10).unlimit!.limit?
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_exists
|
84
|
+
assert User.objects.filter(last_name: 'LimitTest user').exists?
|
85
|
+
assert User.objects.filter(last_name: 'LimitTest user').exist?
|
86
|
+
|
87
|
+
refute User.objects.filter(last_name: 'This user does not exist').exists?
|
88
|
+
refute User.objects.filter(last_name: 'This user does not exist').exist?
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_brackets_index_out_of_range
|
92
|
+
assert_nil User.objects.filter(last_name: 'LimitTest user').order_by(created_at: :ASC)[1000]
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_brackets_invalid_value
|
96
|
+
exception = assert_raises RuntimeError do
|
97
|
+
assert_raises User.objects.filter(last_name: 'LimitTest user').order_by(created_at: :ASC)['INVALID VALUE']
|
98
|
+
end
|
99
|
+
assert_equal('Invalid limit passed to query: INVALID VALUE', exception.message)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_fetch_index_out_of_range
|
103
|
+
exception = assert_raises IndexError do
|
104
|
+
assert_raises User.objects.filter(last_name: 'LimitTest user').order_by(created_at: :ASC).fetch(1000)
|
105
|
+
end
|
106
|
+
assert_equal('Index 1000 outside of QuerySet bounds', exception.message)
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require_relative '../test_helper'
|
3
|
+
|
4
|
+
class LocalSelectionTest < Minitest::Test
|
5
|
+
|
6
|
+
def test_equal_selection
|
7
|
+
local_selection = Babik::Selection::LocalSelection.new(User, 'first_name', 'Pepe')
|
8
|
+
assert_equal local_selection.model, User
|
9
|
+
assert_equal local_selection.selection_path, 'first_name'
|
10
|
+
assert_equal local_selection.selected_field, 'first_name'
|
11
|
+
assert_equal local_selection.value, 'Pepe'
|
12
|
+
assert_equal local_selection.operator, 'equal'
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_selection_icontains
|
16
|
+
local_selection = Babik::Selection::LocalSelection.new(User, 'firstname__icontains', 'Pepe')
|
17
|
+
assert_equal local_selection.model, User
|
18
|
+
assert_equal local_selection.selection_path, 'firstname__icontains'
|
19
|
+
assert_equal local_selection.selected_field, 'firstname'
|
20
|
+
assert_equal local_selection.value, 'Pepe'
|
21
|
+
assert_equal local_selection.operator, 'icontains'
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of different lookups available in both methods filter and exclude
|
7
|
+
class LookupTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
Post.create!(title: 'This other post of 5 stars', stars: 5)
|
11
|
+
Post.create!(title: 'This a post of 5 stars', stars: 5)
|
12
|
+
Post.create!(title: 'This a post of 4 stars', stars: 4)
|
13
|
+
Post.create!(title: 'This a post of 3 stars', stars: 3)
|
14
|
+
Post.create!(title: 'This other post with 3 stars', stars: 3)
|
15
|
+
|
16
|
+
Post.create!(title: 'Old post 1', stars: 0, created_at: Time.now - 1.month)
|
17
|
+
Post.create!(title: 'Old post 2', stars: 0, created_at: Time.now - 10.months)
|
18
|
+
|
19
|
+
Post.create!(title: 'Yesteryear post 1', created_at: Time.now - 1.year)
|
20
|
+
Post.create!(title: 'Yesteryear post 2', created_at: Time.now - 10.year)
|
21
|
+
end
|
22
|
+
|
23
|
+
def teardown
|
24
|
+
Post.destroy_all
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_gt
|
28
|
+
posts_with_more_than_4_starts = Post.objects.filter(stars__gt: 4).order_by(created_at: :ASC)
|
29
|
+
assert_equal 2, posts_with_more_than_4_starts.count
|
30
|
+
assert_equal 'This other post of 5 stars', posts_with_more_than_4_starts[0].title
|
31
|
+
assert_equal 'This a post of 5 stars', posts_with_more_than_4_starts[1].title
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_gte
|
35
|
+
posts_with_more_or_equal_than_4_starts = Post.objects.filter(stars__gte: 4).order_by(created_at: :ASC)
|
36
|
+
assert_equal 3, posts_with_more_or_equal_than_4_starts.count
|
37
|
+
assert_equal 'This other post of 5 stars', posts_with_more_or_equal_than_4_starts[0].title
|
38
|
+
|
39
|
+
assert_nil posts_with_more_or_equal_than_4_starts[100]
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_lt
|
43
|
+
posts_with_less_than_4_starts = Post.objects.filter(stars__lt: 4).order_by(created_at: :ASC)
|
44
|
+
assert_equal 4, posts_with_less_than_4_starts.count
|
45
|
+
assert_equal 'Old post 2', posts_with_less_than_4_starts[0].title
|
46
|
+
assert_equal 'Old post 1', posts_with_less_than_4_starts[1].title
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_lte
|
50
|
+
posts_with_less_or_equal_than_4_starts = Post.objects.filter(stars__lte: 4).order_by(created_at: :ASC)
|
51
|
+
assert_equal 5, posts_with_less_or_equal_than_4_starts.count
|
52
|
+
assert_equal 'Old post 2', posts_with_less_or_equal_than_4_starts[0].title
|
53
|
+
assert_equal 'Old post 1', posts_with_less_or_equal_than_4_starts[1].title
|
54
|
+
assert_equal 'This a post of 4 stars', posts_with_less_or_equal_than_4_starts[2].title
|
55
|
+
assert_equal 'This a post of 3 stars', posts_with_less_or_equal_than_4_starts[3].title
|
56
|
+
assert_equal 'This a post of 3 stars', posts_with_less_or_equal_than_4_starts[3].title
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_in
|
60
|
+
posts_with_odd_stars = Post.objects.filter(stars__in: [5, 3, 1])
|
61
|
+
posts_with_5_stars = Post.objects.filter(stars: 5)
|
62
|
+
posts_with_3_stars = Post.objects.filter(stars: 3)
|
63
|
+
posts_with_1_star = Post.objects.filter(stars: 1)
|
64
|
+
|
65
|
+
assert_equal 2, posts_with_5_stars.count
|
66
|
+
assert_equal 2, posts_with_3_stars.count
|
67
|
+
assert_equal 0, posts_with_1_star.count
|
68
|
+
assert_equal 4, posts_with_odd_stars.count
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_in_and_equal
|
72
|
+
assert_equal Post.objects.filter(stars: 3).count, Post.objects.filter(stars__in: 3).count
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_between
|
76
|
+
posts_3_4_stars = Post.objects.filter(stars__between: [3, 4]).order_by(created_at: :ASC)
|
77
|
+
posts_3_4_stars_range = Post.objects.filter(stars__range: [3, 4]).order_by(created_at: :ASC)
|
78
|
+
assert_equal 3, posts_3_4_stars.count
|
79
|
+
assert_equal 3, posts_3_4_stars_range.count
|
80
|
+
assert_equal 'This a post of 4 stars', posts_3_4_stars[0].title
|
81
|
+
assert_equal 'This a post of 3 stars', posts_3_4_stars[1].title
|
82
|
+
assert_equal 'This other post with 3 stars', posts_3_4_stars[2].title
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_between_dates
|
86
|
+
old_posts = Post.objects.filter(created_at__between: [Time.now - 2.months, Time.now - 1.day])
|
87
|
+
old_posts_range = Post.objects.filter(created_at__range: [Time.now - 2.months, Time.now - 1.day])
|
88
|
+
assert_equal 1, old_posts.count
|
89
|
+
assert_equal 1, old_posts_range.count
|
90
|
+
assert_equal 'Old post 1', old_posts[0].title
|
91
|
+
assert_equal 'Old post 1', old_posts_range[0].title
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_date
|
95
|
+
today_posts = Post.objects.filter(created_at__date: Date.today)
|
96
|
+
assert_equal 5, today_posts.count
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_year
|
100
|
+
younger_than_1998_year_posts = Post.objects.filter(created_at__year__gt: 1998)
|
101
|
+
assert_equal Post.objects.count, younger_than_1998_year_posts.count
|
102
|
+
assert_equal 0, Post.objects.filter(created_at__year: 1998).count
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_quarter
|
106
|
+
# Get a quarter with posts
|
107
|
+
quarters = Post.objects.map { |post| (post.created_at.strftime('%m').to_i + 2) / 3 }
|
108
|
+
grouped_quarters = quarters.group_by(&:itself)
|
109
|
+
quarter = grouped_quarters.keys[0]
|
110
|
+
first_quarter = quarter.to_i
|
111
|
+
this_quarter_posts = Post.objects.filter(created_at__quarter: first_quarter)
|
112
|
+
assert_equal grouped_quarters[quarter].length, this_quarter_posts.count
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_month
|
116
|
+
this_month_posts = Post.objects.filter(created_at__month: Time.now.utc.month)
|
117
|
+
assert_equal 7, this_month_posts.count
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_day
|
121
|
+
this_day_posts = Post.objects.filter(created_at__day: Time.now.utc.day)
|
122
|
+
assert_equal 9, this_day_posts.count
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_hour
|
126
|
+
this_hour_posts = Post.objects.filter(created_at__hour: Time.now.utc.hour)
|
127
|
+
assert_equal 9, this_hour_posts.count
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_hour_wrong_lookup
|
131
|
+
exception = assert_raises RuntimeError do
|
132
|
+
Post.objects.filter(created_at__hour__xx: Time.now.utc.hour)[0]
|
133
|
+
end
|
134
|
+
assert_equal('Unknown lookup xx', exception.message)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_minute
|
138
|
+
this_minute_posts = Post.objects.filter(created_at__minute: Time.now.utc.strftime('%M'))
|
139
|
+
assert_equal 9, this_minute_posts.count
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_second
|
143
|
+
# Get a second with posts
|
144
|
+
seconds = Post.objects.map { |post| post.created_at.strftime('%S') }
|
145
|
+
grouped_seconds = seconds.group_by(&:itself)
|
146
|
+
second = grouped_seconds.keys[0]
|
147
|
+
first_second = second.to_i
|
148
|
+
this_second_posts = Post.objects.filter(created_at__second: first_second)
|
149
|
+
assert_equal grouped_seconds[second].length, this_second_posts.count
|
150
|
+
end
|
151
|
+
|
152
|
+
# Check ISO week
|
153
|
+
def test_week
|
154
|
+
weeks = Post.objects.map { |post| post.created_at.strftime('%V').to_i }
|
155
|
+
grouped_weeks = weeks.group_by(&:itself)
|
156
|
+
first_week = grouped_weeks.keys[0]
|
157
|
+
first_week_int = first_week.to_i
|
158
|
+
this_week_posts = Post.objects.filter(created_at__week: first_week_int)
|
159
|
+
assert_equal grouped_weeks[first_week].length, this_week_posts.count
|
160
|
+
end
|
161
|
+
|
162
|
+
# Check 0-6 (sunday to monday) week day
|
163
|
+
def test_weekday
|
164
|
+
# Get a week day (0-6, sunday to monday) with posts
|
165
|
+
week_days = Post.objects.map { |post| post.created_at.strftime('%w') }
|
166
|
+
grouped_week_days = week_days.group_by(&:itself)
|
167
|
+
first_week_day = grouped_week_days.keys[0]
|
168
|
+
first_week_day_int = first_week_day.to_i
|
169
|
+
this_week_day_posts = Post.objects.filter(created_at__week_day: first_week_day_int)
|
170
|
+
assert_equal grouped_week_days[first_week_day].length, this_week_day_posts.count
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_time
|
174
|
+
# Get a time (HH:MM:SS) with posts
|
175
|
+
times = Post.objects.map { |post| post.created_at.strftime('%H:%M:%S') }
|
176
|
+
grouped_times = times.group_by(&:itself)
|
177
|
+
first_time = grouped_times.keys[0]
|
178
|
+
this_time_posts = Post.objects.filter(created_at__time: first_time)
|
179
|
+
assert_equal grouped_times[first_time].length, this_time_posts.count
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_regex
|
183
|
+
other_posts = Post.objects.filter(title__regex: /This a post of \d+ stars/).order_by(stars: :ASC)
|
184
|
+
if Babik::Database.config[:adapter] == 'sqlite3'
|
185
|
+
assert other_posts.sql.select.include?("posts.title REGEXP 'This a post of \\d+ stars'")
|
186
|
+
return
|
187
|
+
end
|
188
|
+
assert_equal 3, other_posts.count
|
189
|
+
assert_equal 'This a post of 3 stars', other_posts[0].title
|
190
|
+
assert_equal 'This a post of 4 stars', other_posts[1].title
|
191
|
+
assert_equal 'This a post of 5 stars', other_posts[2].title
|
192
|
+
assert_equal 3, other_posts.count
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_iregex
|
196
|
+
other_posts = Post.objects.filter(title__iregex: /This a post of \d+ stars/).order_by(stars: :ASC)
|
197
|
+
if Babik::Database.config[:adapter] == 'sqlite3'
|
198
|
+
assert other_posts.sql.select.include?("posts.title REGEXP '(?i)This a post of \\d+ stars'")
|
199
|
+
return
|
200
|
+
end
|
201
|
+
assert_equal 3, other_posts.count
|
202
|
+
assert_equal 'This a post of 3 stars', other_posts[0].title
|
203
|
+
assert_equal 'This a post of 4 stars', other_posts[1].title
|
204
|
+
assert_equal 'This a post of 5 stars', other_posts[2].title
|
205
|
+
assert_equal 3, other_posts.count
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Tests of none method
|
7
|
+
class NoneTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
[1..100].each do |i|
|
11
|
+
Post.create!(title: "Post #{i}", stars: 5)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
Post.destroy_all
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_none
|
20
|
+
no_posts = Post.objects.none
|
21
|
+
assert_equal 0, no_posts.count
|
22
|
+
i = 100
|
23
|
+
no_posts.each do |_post|
|
24
|
+
i -= 1
|
25
|
+
end
|
26
|
+
assert_equal 100, i
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_deep_none_call
|
30
|
+
no_posts = Post.objects.filter(stars: 5).none
|
31
|
+
assert_equal 0, no_posts.count
|
32
|
+
i = 100
|
33
|
+
no_posts.each do |_post|
|
34
|
+
i -= 1
|
35
|
+
end
|
36
|
+
assert_equal 100, i
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
# Ordering tests
|
7
|
+
class OrderTest < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
|
11
|
+
@frankish_kingdom = GeoZone.create!(name: 'Frankish Kingdom')
|
12
|
+
|
13
|
+
frankish_king_names = [
|
14
|
+
'Merovech',
|
15
|
+
'Childeric I',
|
16
|
+
'Clovis I'
|
17
|
+
]
|
18
|
+
|
19
|
+
@frankish_kings = []
|
20
|
+
frankish_king_names.each do |frankish_king|
|
21
|
+
@frankish_kings << User.create!(first_name: frankish_king, last_name: 'Merovingian', zone: @frankish_kingdom)
|
22
|
+
end
|
23
|
+
|
24
|
+
@hispania = GeoZone.create!(name: 'Hispania')
|
25
|
+
goth_king_names = ['Alarico I',
|
26
|
+
'Ataulfo',
|
27
|
+
'Sigerico',
|
28
|
+
'Teodorico I',
|
29
|
+
'Turismundo',
|
30
|
+
'Teodorico II',
|
31
|
+
'Eurico',
|
32
|
+
'Alarico II']
|
33
|
+
|
34
|
+
@goth_kings = []
|
35
|
+
goth_king_names.each do |goth_king|
|
36
|
+
@goth_kings << User.create!(first_name: goth_king, zone: @hispania)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def teardown
|
42
|
+
User.destroy_all
|
43
|
+
GeoZone.destroy_all
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_first
|
47
|
+
first_user = User.objects.filter('zone::name': 'Hispania').order_by(%i[first_name ASC]).first
|
48
|
+
assert_equal 'Alarico I', first_user.first_name
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_last_asc
|
52
|
+
last_user = User.objects.filter('zone::name': 'Hispania').order_by(%i[first_name ASC]).last
|
53
|
+
assert_equal 'Turismundo', last_user.first_name
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_last_desc
|
57
|
+
last_user = User.objects.filter('zone::name': 'Hispania').order_by(%i[first_name DESC]).last
|
58
|
+
assert_equal 'Alarico I', last_user.first_name
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_first_last
|
62
|
+
first = User.objects.filter('zone::name': 'Hispania').order_by(%i[first_name ASC]).first
|
63
|
+
inverted_last = User.objects.filter('zone::name': 'Hispania').order_by(%i[first_name DESC]).last
|
64
|
+
assert_equal first.id, inverted_last.id
|
65
|
+
assert_equal first.first_name, inverted_last.first_name
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_basic_order
|
69
|
+
users = User.objects.filter('zone::name': 'Hispania').order_by(%i[first_name ASC])
|
70
|
+
_test_basic_order(users)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_basic_order_hash
|
74
|
+
users = User.objects.filter('zone::name': 'Hispania').order_by(first_name: :ASC)
|
75
|
+
_test_basic_order(users)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_basic_order_string
|
79
|
+
users = User.objects.filter('zone::name': 'Hispania').order_by('first_name')
|
80
|
+
_test_basic_order(users)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_basic_order_symbol
|
84
|
+
users = User.objects.filter('zone::name': 'Hispania').order_by(:first_name)
|
85
|
+
_test_basic_order(users)
|
86
|
+
end
|
87
|
+
|
88
|
+
def _test_basic_order(users)
|
89
|
+
goth_king_names = [
|
90
|
+
'Alarico I', 'Alarico II', 'Ataulfo', 'Eurico', 'Sigerico', 'Teodorico I', 'Teodorico II', 'Turismundo'
|
91
|
+
]
|
92
|
+
users.each_with_index do |user, user_index|
|
93
|
+
assert_equal goth_king_names[user_index], user.first_name
|
94
|
+
end
|
95
|
+
assert users.ordered?
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_deep_order
|
99
|
+
users = User.objects.order_by(%i[zone::name ASC], %i[first_name ASC])
|
100
|
+
reversed_users = users.reverse
|
101
|
+
king_names = [
|
102
|
+
'Childeric I',
|
103
|
+
'Clovis I',
|
104
|
+
'Merovech',
|
105
|
+
'Alarico I',
|
106
|
+
'Alarico II',
|
107
|
+
'Ataulfo',
|
108
|
+
'Eurico',
|
109
|
+
'Sigerico',
|
110
|
+
'Teodorico I',
|
111
|
+
'Teodorico II',
|
112
|
+
'Turismundo'
|
113
|
+
]
|
114
|
+
users.each_with_index do |user, user_index|
|
115
|
+
assert_equal king_names[user_index], user.first_name
|
116
|
+
end
|
117
|
+
assert users.ordered?
|
118
|
+
|
119
|
+
reversed_king_names = king_names.reverse
|
120
|
+
reversed_users.each_with_index do |reversed_order_user, user_index|
|
121
|
+
assert_equal reversed_king_names[user_index], reversed_order_user.first_name
|
122
|
+
end
|
123
|
+
assert reversed_users.ordered?
|
124
|
+
|
125
|
+
king_names.each_with_index do |king_name, king_index|
|
126
|
+
assert_equal king_name, users[king_index].first_name
|
127
|
+
assert_equal king_name, reversed_users[king_names.length - king_index - 1].first_name
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_disorder
|
132
|
+
users = User.objects.order_by(%i[zone::name ASC], %i[first_name ASC])
|
133
|
+
users.disorder!
|
134
|
+
refute users.ordered?
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_order_with_prefixed_direction
|
138
|
+
users = User.objects.order_by('-zone::name', '-first_name')
|
139
|
+
first_user = users.first
|
140
|
+
assert_equal 'Hispania', first_user.zone.name
|
141
|
+
assert_equal 'Turismundo', first_user.first_name
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_wrong_order
|
145
|
+
exception = assert_raises RuntimeError do
|
146
|
+
User.objects.filter('zone::name': 'Hispania').order_by([:first_name, 'XXXX'])
|
147
|
+
end
|
148
|
+
assert_equal('Invalid order type XXXX in first_name: Expecting :ASC or :DESC', exception.message)
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_wrong_order_param_type
|
152
|
+
exception = assert_raises RuntimeError do
|
153
|
+
User.objects.filter('zone::name': 'Hispania').order_by(2222)
|
154
|
+
end
|
155
|
+
assert_equal('Invalid type of order: 2222', exception.message)
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_wrong_field_path
|
159
|
+
exception = assert_raises RuntimeError do
|
160
|
+
User.objects.filter('zone::name': 'Hispania').order_by([1111, :ASC])
|
161
|
+
end
|
162
|
+
assert_equal('field_path of class Integer not valid. A Symbol/String/Babik::Selection::Base expected', exception.message)
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|