brainstem 1.1.0 → 1.1.1
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 +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +7 -5
- data/README.md +5 -0
- data/brainstem.gemspec +1 -0
- data/lib/brainstem.rb +14 -0
- data/lib/brainstem/query_strategies/base_strategy.rb +25 -6
- data/lib/brainstem/query_strategies/filter_and_search.rb +2 -1
- data/lib/brainstem/query_strategies/filter_or_search.rb +6 -6
- data/lib/brainstem/version.rb +1 -1
- data/spec/brainstem/presenter_spec.rb +11 -6
- data/spec/brainstem/query_strategies/filter_and_search_spec.rb +44 -0
- data/spec/brainstem/query_strategies/filter_or_search_spec.rb +53 -8
- data/spec/brainstem_spec.rb +11 -0
- data/spec/shared/base_strategy.rb +46 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/spec_helpers/schema.rb +6 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6284bb9b32ad35fb5e88a28ada0cb128a533dbae
|
4
|
+
data.tar.gz: 3f1624b6bde3c0703b3540b70a77566c6312bd7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '06469a9fd4016afafc4c169208eecf714bfc0159ff11a1f3442eefdcfe7406a5017288f146e25f5d4bdc203705fe3b26986ac8adac1d6112e05775898c7b33d4'
|
7
|
+
data.tar.gz: 2fccd29843c5b613e288520a9897f3c0dac7a02bcaf5953bf5dfa4bdeacf876711bf3d07cc65c4f1f14dc725b389c4541a1e002dc865ebc435507521686e474a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
+ **1.1.1 - _01/15/2017_
|
4
|
+
- Add `Brainstem.mysql_use_calc_found_rows` boolean config option to utilize MySQL's [FOUND_ROWS()](https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_found-rows) functionality to avoid issuing a new query to calculate the record count, which has the potential to up to double the response time of the endpoint.
|
5
|
+
|
3
6
|
+ **1.1.0 - _12/18/2017_
|
4
7
|
- Add `meta` key to API responses which includes `page_number`, `page_count`, and `page_size` keys.
|
5
8
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
brainstem (1.1.
|
4
|
+
brainstem (1.1.1)
|
5
5
|
activerecord (>= 4.1)
|
6
6
|
activesupport (>= 4.1)
|
7
7
|
|
@@ -30,21 +30,22 @@ GEM
|
|
30
30
|
i18n (0.9.1)
|
31
31
|
concurrent-ruby (~> 1.0)
|
32
32
|
method_source (0.9.0)
|
33
|
-
minitest (5.
|
33
|
+
minitest (5.11.1)
|
34
|
+
mysql2 (0.3.18)
|
34
35
|
pry (0.9.12.6)
|
35
36
|
coderay (~> 1.0)
|
36
37
|
method_source (~> 0.8)
|
37
38
|
slop (~> 3.4)
|
38
39
|
pry-nav (0.2.4)
|
39
40
|
pry (>= 0.9.10, < 0.11.0)
|
40
|
-
rake (12.
|
41
|
+
rake (12.3.0)
|
41
42
|
redcarpet (3.4.0)
|
42
43
|
rr (1.2.1)
|
43
44
|
rspec (3.7.0)
|
44
45
|
rspec-core (~> 3.7.0)
|
45
46
|
rspec-expectations (~> 3.7.0)
|
46
47
|
rspec-mocks (~> 3.7.0)
|
47
|
-
rspec-core (3.7.
|
48
|
+
rspec-core (3.7.1)
|
48
49
|
rspec-support (~> 3.7.0)
|
49
50
|
rspec-expectations (3.7.0)
|
50
51
|
diff-lcs (>= 1.2.0, < 2.0)
|
@@ -58,7 +59,7 @@ GEM
|
|
58
59
|
thread_safe (0.3.6)
|
59
60
|
tzinfo (1.2.4)
|
60
61
|
thread_safe (~> 0.1)
|
61
|
-
yard (0.9.
|
62
|
+
yard (0.9.12)
|
62
63
|
|
63
64
|
PLATFORMS
|
64
65
|
ruby
|
@@ -67,6 +68,7 @@ DEPENDENCIES
|
|
67
68
|
brainstem!
|
68
69
|
database_cleaner
|
69
70
|
db-query-matchers
|
71
|
+
mysql2
|
70
72
|
pry
|
71
73
|
pry-nav
|
72
74
|
rake
|
data/README.md
CHANGED
@@ -184,6 +184,11 @@ Rails.application.config.to_prepare do
|
|
184
184
|
# Set the current default API namespace.
|
185
185
|
Brainstem.default_namespace = :v1
|
186
186
|
|
187
|
+
# (Optional) Utilize MySQL's [FOUND_ROWS()](https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_found-rows)
|
188
|
+
# functionality to avoid issuing a new query to calculate the record count,
|
189
|
+
# which has the potential to up to double the response time of the endpoint.
|
190
|
+
Brainstem.mysql_use_calc_found_rows = true
|
191
|
+
|
187
192
|
# (Optional) Load a default base helper into all presenters. You could use
|
188
193
|
# this to bring in a concept like `current_user`. # While not necessarily the
|
189
194
|
# best approach, something like http://stackoverflow.com/a/11670283 can
|
data/brainstem.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |gem|
|
|
27
27
|
gem.add_development_dependency "rr"
|
28
28
|
gem.add_development_dependency "rspec", "~> 3.5"
|
29
29
|
gem.add_development_dependency "sqlite3"
|
30
|
+
gem.add_development_dependency "mysql2"
|
30
31
|
gem.add_development_dependency "database_cleaner"
|
31
32
|
gem.add_development_dependency "yard"
|
32
33
|
gem.add_development_dependency "pry"
|
data/lib/brainstem.rb
CHANGED
@@ -21,6 +21,19 @@ module Brainstem
|
|
21
21
|
@default_namespace || "none"
|
22
22
|
end
|
23
23
|
|
24
|
+
# Sets {mysql_use_calc_found_rows} to a new value.
|
25
|
+
# @param [Boolean] bool
|
26
|
+
# @return [Boolean] the new mysql_use_calc_found_rows setting
|
27
|
+
def self.mysql_use_calc_found_rows=(bool)
|
28
|
+
@mysql_use_calc_found_rows = bool
|
29
|
+
end
|
30
|
+
|
31
|
+
# Whether or not to use MYSQL_CALC_FOUND_ROWS to calculate the result set count instead of issuing two queries.
|
32
|
+
# @return [Boolean] the mysql_use_calc_found_rows setting
|
33
|
+
def self.mysql_use_calc_found_rows
|
34
|
+
@mysql_use_calc_found_rows || false
|
35
|
+
end
|
36
|
+
|
24
37
|
# @param [String] namespace
|
25
38
|
# @return [PresenterCollection] the {PresenterCollection} for the given namespace.
|
26
39
|
def self.presenter_collection(namespace = nil)
|
@@ -73,5 +86,6 @@ module Brainstem
|
|
73
86
|
|
74
87
|
@presenter_collection = {}
|
75
88
|
@default_namespace = nil
|
89
|
+
@mysql_use_calc_found_rows = false
|
76
90
|
end
|
77
91
|
end
|
@@ -6,6 +6,7 @@ module Brainstem
|
|
6
6
|
class BaseStrategy
|
7
7
|
def initialize(options)
|
8
8
|
@options = options
|
9
|
+
@last_count = nil
|
9
10
|
end
|
10
11
|
|
11
12
|
def execute(scope)
|
@@ -13,19 +14,24 @@ module Brainstem
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def evaluate_scope(scope)
|
17
|
+
@last_count = nil
|
18
|
+
|
16
19
|
# Load models!
|
17
20
|
# On complex queries, MySQL can sometimes handle 'SELECT id FROM ... ORDER BY ...' much faster than
|
18
21
|
# 'SELECT * FROM ...', so we pluck the ids, then find those specific ids in a separate query.
|
19
|
-
if
|
20
|
-
|
21
|
-
id_lookup = {}
|
22
|
-
ids.each.with_index { |id, index| id_lookup[id] = index }
|
23
|
-
primary_models = scope.klass.where(id: id_lookup.keys).sort_by { |model| id_lookup[model.id] }
|
22
|
+
if ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /mysql|sqlite/i
|
23
|
+
get_ids_sql(scope)
|
24
24
|
else
|
25
|
-
|
25
|
+
scope.to_a
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def evaluate_count(count_scope)
|
30
|
+
ret = @last_count || count_scope.count
|
31
|
+
@last_count = nil
|
32
|
+
ret
|
33
|
+
end
|
34
|
+
|
29
35
|
def calculate_per_page
|
30
36
|
per_page = [(@options[:params][:per_page] || @options[:per_page] || @options[:default_per_page]).to_i, (@options[:max_per_page] || @options[:default_max_per_page]).to_i].min
|
31
37
|
per_page = @options[:default_per_page] if per_page < 1
|
@@ -34,6 +40,19 @@ module Brainstem
|
|
34
40
|
|
35
41
|
private
|
36
42
|
|
43
|
+
def get_ids_sql(scope)
|
44
|
+
if Brainstem.mysql_use_calc_found_rows && ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /mysql/i
|
45
|
+
ids = scope.pluck("SQL_CALC_FOUND_ROWS #{scope.table_name}.id")
|
46
|
+
@last_count = ActiveRecord::Base.connection.execute("SELECT FOUND_ROWS()").first.first
|
47
|
+
else
|
48
|
+
ids = scope.pluck("#{scope.table_name}.id")
|
49
|
+
end
|
50
|
+
|
51
|
+
id_lookup = {}
|
52
|
+
ids.each.with_index { |id, index| id_lookup[id] = index }
|
53
|
+
scope.klass.where(id: id_lookup.keys).sort_by { |model| id_lookup[model.id] }
|
54
|
+
end
|
55
|
+
|
37
56
|
def calculate_limit
|
38
57
|
[[@options[:params][:limit].to_i, 1].max, (@options[:max_per_page] || @options[:default_max_per_page]).to_i].min
|
39
58
|
end
|
@@ -6,10 +6,11 @@ module Brainstem
|
|
6
6
|
scope = @options[:primary_presenter].apply_filters_to_scope(scope, @options[:params], @options)
|
7
7
|
|
8
8
|
if ordering?
|
9
|
-
|
9
|
+
count_scope = scope
|
10
10
|
scope = paginate(scope)
|
11
11
|
scope = @options[:primary_presenter].apply_ordering_to_scope(scope, @options[:params])
|
12
12
|
primary_models = evaluate_scope(scope)
|
13
|
+
count = evaluate_count(count_scope)
|
13
14
|
else
|
14
15
|
filtered_ids = scope.pluck(:id)
|
15
16
|
count = filtered_ids.size
|
@@ -18,18 +18,18 @@ module Brainstem
|
|
18
18
|
|
19
19
|
if @options[:params][:only].present?
|
20
20
|
# Handle Only
|
21
|
-
scope,
|
21
|
+
scope, count_scope = handle_only(scope, @options[:params][:only])
|
22
22
|
else
|
23
23
|
# Paginate
|
24
|
-
scope,
|
24
|
+
scope, count_scope = paginate scope
|
25
25
|
end
|
26
26
|
|
27
|
-
count = count.keys.length if count.is_a?(Hash)
|
28
|
-
|
29
27
|
# Ordering
|
30
28
|
scope = @options[:primary_presenter].apply_ordering_to_scope(scope, @options[:params])
|
31
29
|
|
32
30
|
primary_models = evaluate_scope(scope)
|
31
|
+
count = evaluate_count(count_scope)
|
32
|
+
count = count.keys.length if count.is_a?(Hash)
|
33
33
|
end
|
34
34
|
|
35
35
|
[primary_models, count]
|
@@ -69,12 +69,12 @@ module Brainstem
|
|
69
69
|
|
70
70
|
def paginate(scope)
|
71
71
|
limit, offset = calculate_limit_and_offset
|
72
|
-
[scope.limit(limit).offset(offset).distinct, scope.select("distinct #{scope.connection.quote_table_name @options[:table_name]}.id")
|
72
|
+
[scope.limit(limit).offset(offset).distinct, scope.select("distinct #{scope.connection.quote_table_name @options[:table_name]}.id")]
|
73
73
|
end
|
74
74
|
|
75
75
|
def handle_only(scope, only)
|
76
76
|
ids = (only || "").split(",").select {|id| id =~ /\A\d+\z/}.uniq
|
77
|
-
[scope.where(:id => ids), scope.where(:id => ids)
|
77
|
+
[scope.where(:id => ids), scope.where(:id => ids)]
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/lib/brainstem/version.rb
CHANGED
@@ -747,7 +747,8 @@ describe Brainstem::Presenter do
|
|
747
747
|
end
|
748
748
|
|
749
749
|
sql = presenter.apply_ordering_to_scope(scope, 'order' => 'title').to_sql
|
750
|
-
|
750
|
+
# match SQLite and MySQL quotes
|
751
|
+
expect(sql).to match(/order by workspaces\.title desc, workspaces.id desc, [`"]workspaces[`"]\.[`"]id[`"] ASC/i)
|
751
752
|
# this should be ok, since the first id sort will never have a tie
|
752
753
|
end
|
753
754
|
|
@@ -757,7 +758,8 @@ describe Brainstem::Presenter do
|
|
757
758
|
end
|
758
759
|
|
759
760
|
sql = presenter.apply_ordering_to_scope(scope, 'order' => 'title').to_sql
|
760
|
-
|
761
|
+
# match SQLite and MySQL quotes
|
762
|
+
expect(sql).to match(/order by workspaces\.title desc, [`"]workspaces[`"]\.[`"]id[`"] ASC/i)
|
761
763
|
end
|
762
764
|
end
|
763
765
|
|
@@ -772,7 +774,8 @@ describe Brainstem::Presenter do
|
|
772
774
|
|
773
775
|
it 'applies the named ordering in the given direction and adds the primary key as a fallback sort' do
|
774
776
|
sql = presenter.apply_ordering_to_scope(scope, order).to_sql
|
775
|
-
|
777
|
+
# match SQLite and MySQL quotes
|
778
|
+
expect(sql).to match(/ORDER BY workspaces\.title asc, [`"]workspaces[`"]\.[`"]id[`"] ASC/i)
|
776
779
|
end
|
777
780
|
end
|
778
781
|
|
@@ -781,7 +784,8 @@ describe Brainstem::Presenter do
|
|
781
784
|
|
782
785
|
it 'applies the named ordering in the given direction and adds the primary key as a fallback sort' do
|
783
786
|
sql = presenter.apply_ordering_to_scope(scope, order).to_sql
|
784
|
-
|
787
|
+
# match SQLite and MySQL quotes
|
788
|
+
expect(sql).to match(/order by workspaces\.title asc, [`"]workspaces[`"]\.[`"]id[`"] ASC/i)
|
785
789
|
end
|
786
790
|
end
|
787
791
|
end
|
@@ -791,7 +795,8 @@ describe Brainstem::Presenter do
|
|
791
795
|
|
792
796
|
it 'orders by the primary key' do
|
793
797
|
sql = presenter.apply_ordering_to_scope(scope, order).to_sql
|
794
|
-
|
798
|
+
# match SQLite and MySQL quotes
|
799
|
+
expect(sql).to match(/order by [`"]workspaces[`"]\.[`"]id[`"] ASC/i)
|
795
800
|
end
|
796
801
|
end
|
797
802
|
|
@@ -809,7 +814,7 @@ describe Brainstem::Presenter do
|
|
809
814
|
|
810
815
|
it 'does not add a fallback deterministic sort, and you deserve whatever fate befalls you' do
|
811
816
|
sql = presenter.apply_ordering_to_scope(scope, order).to_sql.squish
|
812
|
-
expect(sql).to
|
817
|
+
expect(sql).to match(/SELECT [`"]workspaces[`"]\.\* FROM [`"]workspaces[`"] WHERE [`"]workspaces[`"]\.[`"]type[`"] IN \('Cthulhu'\) ORDER BY workspaces\.updated_at asc/i)
|
813
818
|
end
|
814
819
|
end
|
815
820
|
end
|
@@ -75,6 +75,50 @@ describe Brainstem::QueryStrategies::FilterAndSearch do
|
|
75
75
|
expect(results.map(&:id)).to eq(expected_paginated_ids)
|
76
76
|
end
|
77
77
|
end
|
78
|
+
|
79
|
+
if(ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /mysql/i)
|
80
|
+
describe 'mysql_use_calc_found_rows' do
|
81
|
+
context 'when using mysql_use_calc_found_rows' do
|
82
|
+
before do
|
83
|
+
Brainstem.mysql_use_calc_found_rows = true
|
84
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(true)
|
85
|
+
end
|
86
|
+
|
87
|
+
after do
|
88
|
+
Brainstem.mysql_use_calc_found_rows = false
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'returns the results without issuing a second query' do
|
92
|
+
expect { run_query }.
|
93
|
+
not_to make_database_queries({ count: 1, matching: "SELECT COUNT(*) FROM" })
|
94
|
+
|
95
|
+
expect { run_query }.
|
96
|
+
to make_database_queries({ count: 1, matching: "SELECT DISTINCT SQL_CALC_FOUND_ROWS cheeses.id FROM" }).
|
97
|
+
and make_database_queries({ count: 1, matching: "SELECT FOUND_ROWS()" })
|
98
|
+
|
99
|
+
_, count = run_query
|
100
|
+
expect(count).to eq(owned_by_bob.count)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when not using mysql_use_calc_found_rows' do
|
105
|
+
before do
|
106
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(false)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'returns the results by issuing a count query' do
|
110
|
+
expect { run_query }.
|
111
|
+
to make_database_queries({ count: 1, matching: "SELECT COUNT(*) FROM" })
|
112
|
+
|
113
|
+
expect { run_query }.
|
114
|
+
not_to make_database_queries({ count: 1, matching: "SELECT DISTINCT SQL_CALC_FOUND_ROWS cheeses.id FROM" })
|
115
|
+
|
116
|
+
expect { run_query }.
|
117
|
+
not_to make_database_queries({ count: 1, matching: "SELECT FOUND_ROWS()" })
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
78
122
|
end
|
79
123
|
|
80
124
|
context 'when no order is specified' do
|
@@ -29,19 +29,64 @@ describe Brainstem::QueryStrategies::FilterOrSearch do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'we are not searching' do
|
32
|
-
let(:
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
let(:options) do
|
33
|
+
{
|
34
|
+
primary_presenter: WorkspacePresenter.new,
|
35
|
+
table_name: 'workspaces',
|
36
|
+
default_per_page: 20,
|
37
|
+
default_max_per_page: 200,
|
38
|
+
params: {}
|
39
|
+
}
|
40
40
|
end
|
41
|
+
let(:subject) { described_class.new(options) }
|
41
42
|
|
42
43
|
it 'returns the primary models and count' do
|
43
44
|
expect(subject.execute(Workspace.unscoped)).to eq([Workspace.unscoped.to_a, Workspace.count])
|
44
45
|
end
|
46
|
+
|
47
|
+
if(ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /mysql/i)
|
48
|
+
describe 'mysql_use_calc_found_rows' do
|
49
|
+
context 'when using mysql_use_calc_found_rows' do
|
50
|
+
before do
|
51
|
+
Brainstem.mysql_use_calc_found_rows = true
|
52
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
after do
|
56
|
+
Brainstem.mysql_use_calc_found_rows = false
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns the results without issuing a second query' do
|
60
|
+
expect { subject.execute(Workspace.unscoped) }.
|
61
|
+
not_to make_database_queries({ count: 1, matching: "SELECT COUNT(*) FROM" })
|
62
|
+
|
63
|
+
expect { subject.execute(Workspace.unscoped) }.
|
64
|
+
to make_database_queries({ count: 1, matching: "SELECT DISTINCT SQL_CALC_FOUND_ROWS workspaces.id FROM" }).
|
65
|
+
and make_database_queries({ count: 1, matching: "SELECT FOUND_ROWS()" })
|
66
|
+
|
67
|
+
_, count = subject.execute(Workspace.unscoped)
|
68
|
+
expect(count).to eq(Workspace.count)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when not using mysql_use_calc_found_rows' do
|
73
|
+
before do
|
74
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(false)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'returns the results by issuing a count query' do
|
78
|
+
expect { subject.execute(Workspace.unscoped) }.
|
79
|
+
to make_database_queries({ count: 1, matching: "SELECT COUNT(distinct `workspaces`.id) FROM" })
|
80
|
+
|
81
|
+
expect { subject.execute(Workspace.unscoped) }.
|
82
|
+
not_to make_database_queries({ count: 1, matching: "SELECT DISTINCT SQL_CALC_FOUND_ROWS workspaces.id FROM" })
|
83
|
+
|
84
|
+
expect { subject.execute(Workspace.unscoped) }.
|
85
|
+
not_to make_database_queries({ count: 1, matching: "SELECT FOUND_ROWS()" })
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
45
90
|
end
|
46
91
|
end
|
47
92
|
end
|
data/spec/brainstem_spec.rb
CHANGED
@@ -12,6 +12,17 @@ describe Brainstem do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
describe "mysql_use_calc_found_rows attribute" do
|
16
|
+
it "can be set and read" do
|
17
|
+
Brainstem.mysql_use_calc_found_rows = true
|
18
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns false if unset" do
|
22
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(false)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
15
26
|
describe "presenter collection method" do
|
16
27
|
it "returns an instance of PresenterCollection" do
|
17
28
|
expect(Brainstem.presenter_collection).to be_a(Brainstem::PresenterCollection)
|
@@ -3,6 +3,52 @@ require "spec_helper"
|
|
3
3
|
shared_examples_for Brainstem::QueryStrategies::BaseStrategy do
|
4
4
|
let(:strategy) { described_class.new(options) }
|
5
5
|
|
6
|
+
if(ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /mysql/i)
|
7
|
+
describe 'mysql_use_calc_found_rows' do
|
8
|
+
let(:options) {{}}
|
9
|
+
|
10
|
+
context 'when using mysql_use_calc_found_rows' do
|
11
|
+
before do
|
12
|
+
Brainstem.mysql_use_calc_found_rows = true
|
13
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(true)
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
Brainstem.mysql_use_calc_found_rows = false
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns the results without issuing a second query' do
|
21
|
+
expect { strategy.evaluate_scope(Workspace.unscoped) }.
|
22
|
+
to make_database_queries({ count: 1, matching: "SELECT SQL_CALC_FOUND_ROWS workspaces.id FROM" }).
|
23
|
+
and make_database_queries({ count: 1, matching: "SELECT FOUND_ROWS()" })
|
24
|
+
|
25
|
+
count_scope_that_should_not_be_used = Workspace.none
|
26
|
+
count_expected = Workspace.count
|
27
|
+
|
28
|
+
expect {
|
29
|
+
expect(strategy.evaluate_count(count_scope_that_should_not_be_used)).to eq(count_expected)
|
30
|
+
}.not_to make_database_queries
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when not using mysql_use_calc_found_rows' do
|
35
|
+
before do
|
36
|
+
expect(Brainstem.mysql_use_calc_found_rows).to eq(false)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns the results by issuing a count query' do
|
40
|
+
expect { strategy.evaluate_scope(Workspace.unscoped) }.
|
41
|
+
not_to make_database_queries({ count: 1, matching: "SELECT SQL_CALC_FOUND_ROWS workspaces.id FROM" })
|
42
|
+
expect { strategy.evaluate_scope(Workspace.unscoped) }.
|
43
|
+
not_to make_database_queries({ count: 1, matching: "SELECT FOUND_ROWS()" })
|
44
|
+
|
45
|
+
expect { strategy.evaluate_count(Workspace.unscoped) }.
|
46
|
+
to make_database_queries({ count: 1, matching: "SELECT COUNT(*) FROM" })
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
6
52
|
describe "#calculate_per_page" do
|
7
53
|
let(:result) { strategy.calculate_per_page }
|
8
54
|
|
data/spec/spec_helper.rb
CHANGED
data/spec/spec_helpers/schema.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
if ENV['USE_MYSQL']
|
2
|
+
ActiveRecord::Base.establish_connection(:adapter => 'mysql2', :database => 'test', :username => 'root', :password => '', :host => '127.0.0.1')
|
3
|
+
else
|
4
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
5
|
+
end
|
6
|
+
|
2
7
|
ActiveRecord::Schema.define do
|
3
8
|
self.verbose = false
|
4
9
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brainstem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mavenlink
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: mysql2
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: database_cleaner
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|