trailblazer-finder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +45 -0
- data/.rubocop_todo.yml +52 -0
- data/.travis.yml +15 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +23 -0
- data/README.md +494 -0
- data/Rakefile +29 -0
- data/lib/trailblazer/finder/adapters/active_record/paging.rb +20 -0
- data/lib/trailblazer/finder/adapters/active_record/sorting.rb +20 -0
- data/lib/trailblazer/finder/adapters/active_record.rb +30 -0
- data/lib/trailblazer/finder/adapters/data_mapper/paging.rb +20 -0
- data/lib/trailblazer/finder/adapters/data_mapper/sorting.rb +25 -0
- data/lib/trailblazer/finder/adapters/data_mapper.rb +30 -0
- data/lib/trailblazer/finder/adapters/friendly_id.rb +33 -0
- data/lib/trailblazer/finder/adapters/kaminari.rb +18 -0
- data/lib/trailblazer/finder/adapters/sequel/paging.rb +20 -0
- data/lib/trailblazer/finder/adapters/sequel/sorting.rb +25 -0
- data/lib/trailblazer/finder/adapters/sequel.rb +30 -0
- data/lib/trailblazer/finder/adapters/will_paginate.rb +18 -0
- data/lib/trailblazer/finder/adapters.rb +26 -0
- data/lib/trailblazer/finder/base.rb +98 -0
- data/lib/trailblazer/finder/errors/block_ignored.rb +11 -0
- data/lib/trailblazer/finder/errors/invalid_defined_by_value.rb +11 -0
- data/lib/trailblazer/finder/errors/invalid_number.rb +16 -0
- data/lib/trailblazer/finder/errors/missing_entity_type.rb +11 -0
- data/lib/trailblazer/finder/errors/with_ignored.rb +11 -0
- data/lib/trailblazer/finder/features/paging.rb +55 -0
- data/lib/trailblazer/finder/features/sorting.rb +66 -0
- data/lib/trailblazer/finder/features.rb +22 -0
- data/lib/trailblazer/finder/filter.rb +66 -0
- data/lib/trailblazer/finder/find.rb +29 -0
- data/lib/trailblazer/finder/utils/extra.rb +31 -0
- data/lib/trailblazer/finder/utils/params.rb +28 -0
- data/lib/trailblazer/finder/utils/parse.rb +25 -0
- data/lib/trailblazer/finder/utils/string.rb +35 -0
- data/lib/trailblazer/finder/version.rb +5 -0
- data/lib/trailblazer/finder.rb +29 -0
- data/lib/trailblazer/operation/finder.rb +61 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/spec_helper_active_record.rb +50 -0
- data/spec/spec_helper_data_mapper.rb +35 -0
- data/spec/spec_helper_sequel.rb +32 -0
- data/spec/support/paging_shared_example.rb +65 -0
- data/spec/support/sorting_shared_example.rb +95 -0
- data/spec/trailblazer/finder/adapters/active_record/base_spec.rb +112 -0
- data/spec/trailblazer/finder/adapters/active_record/paging_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/active_record/sorting_spec.rb +82 -0
- data/spec/trailblazer/finder/adapters/data_mapper/base_spec.rb +112 -0
- data/spec/trailblazer/finder/adapters/data_mapper/paging_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/data_mapper/sorting_spec.rb +85 -0
- data/spec/trailblazer/finder/adapters/friendly_id_spec.rb +46 -0
- data/spec/trailblazer/finder/adapters/kaminari_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/sequel/base_spec.rb +112 -0
- data/spec/trailblazer/finder/adapters/sequel/paging_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/sequel/sorting_spec.rb +82 -0
- data/spec/trailblazer/finder/adapters/will_paginate_spec.rb +71 -0
- data/spec/trailblazer/finder/adapters_spec.rb +110 -0
- data/spec/trailblazer/finder/base_spec.rb +329 -0
- data/spec/trailblazer/finder/features/paging_spec.rb +104 -0
- data/spec/trailblazer/finder/features/sorting_spec.rb +100 -0
- data/spec/trailblazer/finder/features_spec.rb +55 -0
- data/spec/trailblazer/finder/filter_spec.rb +133 -0
- data/spec/trailblazer/finder/find_spec.rb +72 -0
- data/spec/trailblazer/finder/utils/extra_spec.rb +41 -0
- data/spec/trailblazer/finder/utils/params_spec.rb +39 -0
- data/spec/trailblazer/finder/utils/parse_spec.rb +33 -0
- data/spec/trailblazer/finder/utils/string_spec.rb +25 -0
- data/spec/trailblazer/operation/finder_spec.rb +103 -0
- data/spec/trailblazer/operation/paging_spec.rb +68 -0
- data/spec/trailblazer/operation/sorting_spec.rb +80 -0
- data/trailblazer-finder.gemspec +41 -0
- metadata +402 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper_active_record'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
describe ActiveRecord do
|
7
|
+
# it_behaves_like 'a base orm adapter'
|
8
|
+
|
9
|
+
after do
|
10
|
+
Product.delete_all
|
11
|
+
end
|
12
|
+
|
13
|
+
def define_finder_class(&block)
|
14
|
+
Class.new(Trailblazer::Finder) do
|
15
|
+
class_eval(&block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def finder_class(&block) # rubocop:disable Metrics/MethodLength
|
20
|
+
define_finder_class do
|
21
|
+
adapters ActiveRecord
|
22
|
+
|
23
|
+
entity_type { Product }
|
24
|
+
|
25
|
+
filter_by :id
|
26
|
+
filter_by :name
|
27
|
+
filter_by :slug
|
28
|
+
|
29
|
+
if block.nil?
|
30
|
+
filter_by :value do |entity_type, value|
|
31
|
+
entity_type.where(slug: value)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
class_eval(&block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def finder_with_filter(key = nil, name = nil, &block)
|
40
|
+
finder_class(&block).new filter: { key => name }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'filter_by' do
|
44
|
+
it 'has a default filter' do
|
45
|
+
10.times { |i| Product.create name: "product_#{i}" }
|
46
|
+
finder = finder_with_filter :name, 'product_2'
|
47
|
+
|
48
|
+
expect(finder.results.first.name).to eq 'product_2'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'has another default filter' do
|
52
|
+
10.times { |i| Product.create slug: "product_#{i}" }
|
53
|
+
finder = finder_with_filter :value, 'product_2'
|
54
|
+
|
55
|
+
expect(finder.results.first.slug).to eq 'product_2'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'can use methods from the object' do
|
60
|
+
2.times { |i| Product.create name: "product_#{i}" }
|
61
|
+
finder1 = finder_with_filter :id, 1 do
|
62
|
+
filter_by :id do |entity_type, value|
|
63
|
+
some_instance_method(entity_type, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def some_instance_method(entity_type, value)
|
69
|
+
entity_type.where(id: value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
expect(finder1.results.first.id).to eq 1
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'can dispatch with instance methods' do
|
77
|
+
2.times { |i| Product.create name: "product_#{i}" }
|
78
|
+
finder = finder_with_filter :id, 3 do
|
79
|
+
filter_by :id, with: :some_instance_method
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def some_instance_method(entity_type, value)
|
84
|
+
entity_type.where(id: value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
expect(finder.results.first.id).to eq 3
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'filter_by attributes' do
|
92
|
+
it 'accesses filter values' do
|
93
|
+
finder = finder_with_filter :value, 1
|
94
|
+
expect(finder.value).to eq 1
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'returns default filter value if filter_by is not specified' do
|
98
|
+
finder = finder_with_filter do
|
99
|
+
filter_by :value, 1
|
100
|
+
end
|
101
|
+
expect(finder.value).to eq 1
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'does not include invalid filters' do
|
105
|
+
finder = finder_with_filter invalid: 'option'
|
106
|
+
expect { finder.invalid }.to raise_error NoMethodError
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper_active_record'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
module ActiveRecord
|
7
|
+
describe Paging do
|
8
|
+
it_behaves_like 'a paging feature'
|
9
|
+
|
10
|
+
after do
|
11
|
+
Product.delete_all
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_finder_class(&block)
|
15
|
+
Class.new do
|
16
|
+
include Trailblazer::Finder::Base
|
17
|
+
include Trailblazer::Finder::Features::Paging
|
18
|
+
include Trailblazer::Finder::Adapters::ActiveRecord
|
19
|
+
|
20
|
+
instance_eval(&block) if block_given?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def finder_class
|
25
|
+
define_finder_class do
|
26
|
+
entity_type { Product }
|
27
|
+
|
28
|
+
per_page 2
|
29
|
+
|
30
|
+
min_per_page 2
|
31
|
+
max_per_page 10
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def finder_with_page(page = nil, per_page = nil)
|
36
|
+
finder_class.new page: page, per_page: per_page
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can be inherited' do
|
40
|
+
child_class = Class.new(finder_class)
|
41
|
+
expect(child_class.new.per_page).to eq 2
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#results' do
|
45
|
+
it 'paginates results' do
|
46
|
+
6.times { |i| Product.create name: "product_#{i}" }
|
47
|
+
finder = finder_with_page 2, 2
|
48
|
+
|
49
|
+
expect(finder.results.map(&:name)).to eq %w[product_2 product_3]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#count' do
|
54
|
+
it 'gives the real count' do
|
55
|
+
10.times { |i| Product.create name: "product_#{i}" }
|
56
|
+
finder = finder_with_page 1
|
57
|
+
expect(finder.count).to eq 10
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper_active_record'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
module ActiveRecord
|
7
|
+
describe Sorting do
|
8
|
+
def finder_class
|
9
|
+
Class.new do
|
10
|
+
include Trailblazer::Finder::Base
|
11
|
+
include Trailblazer::Finder::Features::Sorting
|
12
|
+
include Trailblazer::Finder::Adapters::ActiveRecord
|
13
|
+
|
14
|
+
entity_type { Product.all }
|
15
|
+
|
16
|
+
sortable_by :name, :price, :created_at
|
17
|
+
|
18
|
+
filter_by :name
|
19
|
+
filter_by :price
|
20
|
+
filter_by(:category) { |entity_type, _| entity_type.joins(:category) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def finder_with_sort(sort = nil, filters = {})
|
25
|
+
finder_class.new filter: { sort: sort }.merge(filters)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can be inherited' do
|
29
|
+
child_class = Class.new(finder_class)
|
30
|
+
expect(child_class.new.sort_attribute).to eq 'name'
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'sorting' do
|
34
|
+
after do
|
35
|
+
Product.delete_all
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sorts results based on the sort option desc' do
|
39
|
+
5.times { |i| Product.create! price: i }
|
40
|
+
|
41
|
+
finder = finder_with_sort 'price desc'
|
42
|
+
expect(finder.results.map(&:price)).to eq [4, 3, 2, 1, 0]
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'sorts results based on the sort option asc' do
|
46
|
+
5.times { |i| Product.create! price: i }
|
47
|
+
|
48
|
+
finder = finder_with_sort 'price asc'
|
49
|
+
expect(finder.results.map(&:price)).to eq [0, 1, 2, 3, 4]
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'defaults to first sort by option' do
|
53
|
+
5.times { |i| Product.create! name: "Name#{i}" }
|
54
|
+
|
55
|
+
finder = finder_with_sort
|
56
|
+
expect(finder.results.map(&:name)).to eq %w[Name4 Name3 Name2 Name1 Name0]
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'ignores invalid sort values' do
|
60
|
+
finder = finder_with_sort 'invalid attribute'
|
61
|
+
expect { finder.results.to_a }.not_to raise_error
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'can handle renames of sorting in joins' do
|
65
|
+
older_category = Category.create! title: 'older'
|
66
|
+
newer_category = Category.create! title: 'newer'
|
67
|
+
|
68
|
+
product_of_newer_category = Product.create! name: 'older product', category: newer_category
|
69
|
+
product_of_older_category = Product.create! name: 'newer product', category: older_category
|
70
|
+
|
71
|
+
finder = finder_with_sort 'created_at desc', category: ''
|
72
|
+
|
73
|
+
expect(finder.results.map(&:name)).to eq [product_of_older_category.name, product_of_newer_category.name]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it_behaves_like 'a sorting feature'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper_data_mapper'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
describe DataMapper do
|
7
|
+
# it_behaves_like 'a base orm adapter'
|
8
|
+
|
9
|
+
after do
|
10
|
+
DProduct.all.destroy
|
11
|
+
end
|
12
|
+
|
13
|
+
def define_finder_class(&block)
|
14
|
+
Class.new(Trailblazer::Finder) do
|
15
|
+
class_eval(&block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def finder_class(&block) # rubocop:disable Metrics/MethodLength
|
20
|
+
define_finder_class do
|
21
|
+
adapters DataMapper
|
22
|
+
|
23
|
+
entity_type { DProduct }
|
24
|
+
|
25
|
+
filter_by :id
|
26
|
+
filter_by :name
|
27
|
+
filter_by :slug
|
28
|
+
|
29
|
+
if block.nil?
|
30
|
+
filter_by :value do |entity_type, value|
|
31
|
+
entity_type.all(slug: value)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
class_eval(&block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def finder_with_filter(key = nil, name = nil, &block)
|
40
|
+
finder_class(&block).new filter: { key => name }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'filter_by' do
|
44
|
+
it 'has a default filter' do
|
45
|
+
10.times { |i| DProduct.create name: "product_#{i}" }
|
46
|
+
finder = finder_with_filter :name, 'product_2'
|
47
|
+
|
48
|
+
expect(finder.results.first.name).to eq 'product_2'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'has another default filter' do
|
52
|
+
10.times { |i| DProduct.create slug: "product_#{i}" }
|
53
|
+
finder = finder_with_filter :value, 'product_2'
|
54
|
+
|
55
|
+
expect(finder.results.first.slug).to eq 'product_2'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'can use methods from the object' do
|
60
|
+
2.times { |i| DProduct.create name: "product_#{i}" }
|
61
|
+
finder1 = finder_with_filter :id, 1 do
|
62
|
+
filter_by :id do |entity_type, value|
|
63
|
+
some_instance_method(entity_type, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def some_instance_method(entity_type, value)
|
69
|
+
entity_type.all(id: value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
expect(finder1.results.first.id).to eq 1
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'can dispatch with instance methods' do
|
77
|
+
2.times { |i| DProduct.create name: "product_#{i}" }
|
78
|
+
finder = finder_with_filter :id, 3 do
|
79
|
+
filter_by :id, with: :some_instance_method
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def some_instance_method(entity_type, value)
|
84
|
+
entity_type.all(id: value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
expect(finder.results.first.id).to eq 3
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'filter_by attributes' do
|
92
|
+
it 'accesses filter values' do
|
93
|
+
finder = finder_with_filter :value, 1
|
94
|
+
expect(finder.value).to eq 1
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'returns default filter value if filter_by is not specified' do
|
98
|
+
finder = finder_with_filter do
|
99
|
+
filter_by :value, 1
|
100
|
+
end
|
101
|
+
expect(finder.value).to eq 1
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'does not include invalid filters' do
|
105
|
+
finder = finder_with_filter invalid: 'option'
|
106
|
+
expect { finder.invalid }.to raise_error NoMethodError
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper_data_mapper'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
module DataMapper
|
7
|
+
describe Paging do
|
8
|
+
it_behaves_like 'a paging feature'
|
9
|
+
|
10
|
+
after do
|
11
|
+
DProduct.all.destroy
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_finder_class(&block)
|
15
|
+
Class.new do
|
16
|
+
include Trailblazer::Finder::Base
|
17
|
+
include Trailblazer::Finder::Features::Paging
|
18
|
+
include Trailblazer::Finder::Adapters::DataMapper
|
19
|
+
|
20
|
+
instance_eval(&block) if block_given?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def finder_class
|
25
|
+
define_finder_class do
|
26
|
+
entity_type { DProduct }
|
27
|
+
|
28
|
+
per_page 2
|
29
|
+
|
30
|
+
min_per_page 2
|
31
|
+
max_per_page 10
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def finder_with_page(page = nil, per_page = nil)
|
36
|
+
finder_class.new page: page, per_page: per_page
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can be inherited' do
|
40
|
+
child_class = Class.new(finder_class)
|
41
|
+
expect(child_class.new.per_page).to eq 2
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#results' do
|
45
|
+
it 'paginates results' do
|
46
|
+
6.times { |i| DProduct.create name: "product_#{i}" }
|
47
|
+
finder = finder_with_page 2, 2
|
48
|
+
|
49
|
+
expect(finder.results.map(&:name)).to eq %w[product_2 product_3]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#count' do
|
54
|
+
it 'gives the real count' do
|
55
|
+
10.times { |i| DProduct.create name: "product_#{i}" }
|
56
|
+
finder = finder_with_page 1
|
57
|
+
expect(finder.count).to eq 10
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper_data_mapper'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
module DataMapper
|
7
|
+
describe Sorting do
|
8
|
+
def finder_class
|
9
|
+
Class.new do
|
10
|
+
include Trailblazer::Finder::Base
|
11
|
+
include Trailblazer::Finder::Features::Sorting
|
12
|
+
include Trailblazer::Finder::Adapters::DataMapper
|
13
|
+
|
14
|
+
entity_type { DProduct }
|
15
|
+
|
16
|
+
sortable_by :name, :price, :created_at
|
17
|
+
|
18
|
+
filter_by :name
|
19
|
+
filter_by :price
|
20
|
+
|
21
|
+
# # Need to find a fix for this, not sure how to handle joins with data mapper properly
|
22
|
+
# filter_by(:d_category) { |entity_type, _| entity_type }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finder_with_sort(sort = nil, filters = {})
|
27
|
+
finder_class.new filter: { sort: sort }.merge(filters)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'can be inherited' do
|
31
|
+
child_class = Class.new(finder_class)
|
32
|
+
expect(child_class.new.sort_attribute).to eq 'name'
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'sorting' do
|
36
|
+
after do
|
37
|
+
DProduct.all.destroy
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'sorts results based on the sort option desc' do
|
41
|
+
5.times { |i| DProduct.create price: i }
|
42
|
+
|
43
|
+
finder = finder_with_sort 'price desc'
|
44
|
+
expect(finder.results.map(&:price)).to eq [4, 3, 2, 1, 0]
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'sorts results based on the sort option asc' do
|
48
|
+
5.times { |i| DProduct.create price: i }
|
49
|
+
|
50
|
+
finder = finder_with_sort 'price asc'
|
51
|
+
expect(finder.results.map(&:price)).to eq [0, 1, 2, 3, 4]
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'defaults to first sort by option' do
|
55
|
+
5.times { |i| DProduct.create name: "Name#{i}" }
|
56
|
+
|
57
|
+
finder = finder_with_sort
|
58
|
+
expect(finder.results.map(&:name)).to eq %w[Name4 Name3 Name2 Name1 Name0]
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'ignores invalid sort values' do
|
62
|
+
finder = finder_with_sort 'invalid attribute'
|
63
|
+
expect { finder.results.to_a }.not_to raise_error
|
64
|
+
end
|
65
|
+
|
66
|
+
# TODO: Need to find a fix for this, not sure how to handle joins with data mapper properly
|
67
|
+
it 'can handle renames of sorting in joins' do
|
68
|
+
# older_category = DCategory.create title: 'older'
|
69
|
+
# newer_category = DCategory.create title: 'newer'
|
70
|
+
#
|
71
|
+
# product_of_newer_category = DProduct.create name: 'older product', d_category: newer_category
|
72
|
+
# product_of_older_category = DProduct.create name: 'newer product', d_category: older_category
|
73
|
+
#
|
74
|
+
# finder = finder_with_sort 'created_at desc', d_category: ''
|
75
|
+
#
|
76
|
+
# expect(finder.results.map(&:name)).to eq [product_of_older_category.name, product_of_newer_category.name]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it_behaves_like 'a sorting feature'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper_active_record'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Finder
|
5
|
+
module Adapters
|
6
|
+
describe FriendlyId do
|
7
|
+
after do
|
8
|
+
Product.delete_all
|
9
|
+
end
|
10
|
+
|
11
|
+
def finder_class
|
12
|
+
Class.new(Trailblazer::Finder) do
|
13
|
+
adapters ActiveRecord, FriendlyId
|
14
|
+
|
15
|
+
entity_type { Product }
|
16
|
+
|
17
|
+
filter_by :name
|
18
|
+
filter_by :price
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def finder_with_slug(slug = nil, filters = {})
|
23
|
+
finder_class.new filter: { id: slug }.merge(filters)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'filters by slug' do
|
27
|
+
2.times { |i| Product.create name: "Product #{i}", price: i, slug: "product_#{i}" }
|
28
|
+
finder = finder_with_slug 'product_1'
|
29
|
+
expect(finder.results.map(&:name)).to eq ['Product 1']
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'filters by id' do
|
33
|
+
2.times { |i| Product.create name: "Product #{i}", price: i, slug: "product_#{i}" }
|
34
|
+
finder = finder_with_slug Product.last.id
|
35
|
+
expect(finder.results.map(&:name)).to match_array([Product.last.name])
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns no records when slug is not found' do
|
39
|
+
2.times { |i| Product.create name: "Product #{i}", price: i, slug: "product_#{i}" }
|
40
|
+
finder = finder_with_slug 'unknown_1'
|
41
|
+
expect(finder.count).to eq 0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper_active_record'
|
2
|
+
require 'kaminari'
|
3
|
+
|
4
|
+
module Trailblazer
|
5
|
+
class Finder
|
6
|
+
module Adapters
|
7
|
+
describe Kaminari do
|
8
|
+
it_behaves_like 'a paging feature'
|
9
|
+
|
10
|
+
after do
|
11
|
+
Product.delete_all
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_finder_class(&block)
|
15
|
+
Class.new do
|
16
|
+
include Trailblazer::Finder::Base
|
17
|
+
include Trailblazer::Finder::Features::Paging
|
18
|
+
include Trailblazer::Finder::Adapters::ActiveRecord
|
19
|
+
include Trailblazer::Finder::Adapters::Kaminari
|
20
|
+
|
21
|
+
instance_eval(&block) if block_given?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def finder_class
|
26
|
+
define_finder_class do
|
27
|
+
entity_type { Product }
|
28
|
+
|
29
|
+
per_page 2
|
30
|
+
|
31
|
+
min_per_page 2
|
32
|
+
max_per_page 10
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def finder_with_page(page = nil, per_page = nil)
|
37
|
+
finder_class.new page: page, per_page: per_page
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can be inherited' do
|
41
|
+
child_class = Class.new(finder_class)
|
42
|
+
expect(child_class.new.per_page).to eq 2
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#results' do
|
46
|
+
it 'paginates results' do
|
47
|
+
6.times { |i| Product.create name: "product_#{i}" }
|
48
|
+
finder = finder_with_page 2, 2
|
49
|
+
|
50
|
+
expect(finder.results.map(&:name)).to eq %w[product_2 product_3]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#count' do
|
55
|
+
it 'gives the real count' do
|
56
|
+
10.times { |i| Product.create name: "product_#{i}" }
|
57
|
+
finder = finder_with_page 1
|
58
|
+
expect(finder.count).to eq 10
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|